繁体   English   中英

将.getClass()强制转换为类型参数

[英]Casting .getClass() to a type parameter

我有一个通用的方法,我需要获取参数的类:

public static<S> void doSomething(S inst) {
  @SuppressWarnings("unchecked")
  Class<? extends S> cls = (Class<? extends S>) inst.getClass();
  // do something with 'cls' and with 'inst'...
}

事实证明,从编译器的类型系统的角度来看, .getClass()返回一个Class<?>因此向下转换为Class<? extends S> Class<? extends S> ,这是一个未经检查的演员表。

我的问题如下:在什么情况下,这种下线是不安全的?

IIUC,此方法的所有调用站点必须传递inst参数的值,该参数是静态(编译时)类型S.值的动态(运行时)类型D必须是S或子类型它们。 因此,inst.getClass()将返回Class<D>对象,假设DS的子类型,则该对象应该可赋值给Class<? extends S> Class<? extends S>

我不确定它是否会对你有所帮助,但我试图找到一个示例情况,当这个类演员可能是危险的。

public static <S> void doSomething(S inst, Consumer<S> newInstConsumer) throws IllegalAccessException, InstantiationException {
    inst = (S) new Object();                                        // just a line of wrong code here
    Class<? extends S> cls = (Class<? extends S>) inst.getClass();  // and if we don't check here
    S newInstance = cls.newInstance();
    newInstConsumer.accept(newInstance);                            // this code fails only here
}

@SuppressWarnings("unchecked")
public static void main(String... args) throws InstantiationException, IllegalAccessException {
    doSomething(new HelloWorldPrinter(), HelloWorldPrinter::print);
}

在什么情况下,这种下线是不安全的?

inst.getClass()的返回类型是Class<? extends |X|> Class<? extends |X|> ,其中|X| 是表达式inst的编译时类型的擦除。 这里, |X| S的擦除,它是Object 这就是为什么它是Class<?>而不是Class<? extends S> Class<? extends S>

擦除是必要的原因是S可能是参数化类型,但只有在Class的类型参数中才应使用reified类型,因为Class对象仅表示具体类型。 例如,你可以传入inst作为一个ArrayList<String> ,但是获得一个Class<? extends ArrayList<String>> Class<? extends ArrayList<String>>

为什么有一个Class<? extends ArrayList<String>>不安全Class<? extends ArrayList<String>> Class<? extends ArrayList<String>> 好吧,例如,您可以使用其.cast()方法将任何内容转换为ArrayList<String>而不会发出任何警告。 但是像.cast()这样的运行时类型检查只能检查已确定的类型( Class对象本身只表示一个具体的类型); 他们无法检查类型参数(在运行时不存在)。 因此,使用.cast()您实际上可以在没有警告的情况下进行未经检查的强制转换,这很糟糕。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM