Typesafe forName类加载

TC1*_*TC1 8 java generics

Class.forName()结果是通用类型时如何调用?通常我都可以使用asSubclass(),但是在这里,我看到的唯一方法就是演员阵容,当其他所有东西都很好地输入泛型时,它会突然出现并让我烦恼.

场景如下:

有一个带有一个入口点主类的.jar main().它需要一个类名的选项(以及其他一些,在这里无关紧要).给出了类的实现Callable<Integer>.此类已加载,初始化和启动.

这是我需要的一个例子:

Class<? extends Callable<Integer>> clazz = (Class<? extends Callable<Integer>>) Class.forName(options.valueOf(className)).asSubclass(Callable.class);
Run Code Online (Sandbox Code Playgroud)

有没有办法摆脱那个演员?

使用SE6.

irr*_*ble 10

首先,你可能想要一个完整的通用 Class

Class<Callable<Integer>> classCI = ...;
Run Code Online (Sandbox Code Playgroud)

然后java类型系统没有问题

Class<? extends Callable<Integer>> clazz =     
    Class.forName(options.valueOf(className))
    .asSubclass(classCI);
Run Code Online (Sandbox Code Playgroud)

我们怎么能得到classCI?我们可以通过未经检查的演员作弊

Class<Callable<Integer>> classCI = (Class<Callable<Integer>>)Callable.class;
Run Code Online (Sandbox Code Playgroud)

这本质上是不安全的.必须有外力来确保className真的是一个Callable<Integer>.例如,如果它是a 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
Run Code Online (Sandbox Code Playgroud)

只要在运行时转换失败时立即抛出异常.

为了安全,我们必须主动检查通用类型 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; 
}
Run Code Online (Sandbox Code Playgroud)

我们有理由在这里禁止"unchecked",因为实现检查以确保如果它className实际上并不表示实现类Callable<Integer>,它会立即抛出异常.我们的演员阵容被"检查",程序是类型安全的.