结果为泛型类型时,如何调用Class.forName()?通常,我可以使用asSubclass(),但是在这里,我看到的唯一方法是强制转换,当使用泛型很好地键入其他内容时,这种方法会出现并困扰我。

该场景是这样的:

有一个带有一个main()入口点主类的.jar。它需要一个类名(与此处无关)。给定的类实现Callable<Integer>。此类已加载,初始化和启动。

这是我需要的一个例子:

Class<? extends Callable<Integer>> clazz = (Class<? extends Callable<Integer>>) Class.forName(options.valueOf(className)).asSubclass(Callable.class);

有什么方法可以摆脱这种情况吗?

使用SE6。

最佳答案

首先,您可能需要完整的通用Class

Class<Callable<Integer>> classCI = ...;

然后java类型系统没有问题
Class<? extends Callable<Integer>> clazz =
    Class.forName(options.valueOf(className))
    .asSubclass(classCI);

我们如何获得classCI?我们可以通过未经检查的 Actor 作弊
Class<Callable<Integer>> classCI = (Class<Callable<Integer>>)Callable.class;

这本质上是不安全的。必须有外部力量来确保className确实是Callable<Integer>。例如,如果它是Callable<String>,则程序将在所有强制类型转换中运行,而不会出现任何问题,并且只有在调用Integer call()时,它才会被炸毁,并且错误消息将极具误导性。

如果无法静态分析类型转换是否成功,也可以:
Object o = ...;
String s1 = (String)o; // may fail, no javac warning
String s2 = String.class.cast(o); // may fail, no javac warning

只要在运行时强制转换失败时立即引发异常即可。

为了确保类型安全,我们必须主动检查className的通用类型
@SuppressWarning( "unchecked" )
Class<? Callable<Integer>> getClass(String className)
{
    Class clazz = Class.forName(className);
    via reflection, check generic super interfaces of clazz
    if there's no Callable<Integer> super interface
        throw "className is not a Callable<Integer>"

    // we have *checked*, the following cast is safe
    return (Class<? Callable<Integer>>)clazz;
}

我们有理由在这里取消“unchecked”,因为实现会进行检查以确保className并非真正表示实现Callable<Integer>的类,它会立即在此处抛出异常。我们的类型转换已“选中”,程序是类型安全的。

关于java - Typesafe forName类加载,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6197802/

10-12 03:57