繁体   English   中英

为什么Class.getClass()可以与Class.cast()返回类型不同?

[英]Why Class.getClass() can be different from Class.cast() return type?

我希望你能帮助我解决这个问题。

我一直在寻找这个问题的答案,但我能找到的只是通用类型用法或关于反射的一般说明。

假设我们有一个父类和一个扩展该父类的子类。 所以,见下文:

Parent v = new Child();

如果我创建v.getClass()它返回Child 但是,如果我创建v.getClass().cast()它将从类型Parent返回一个对象。

谁知道为什么会这样? 我还看了一下Java API文档,找不到原因......

谢谢你的任何想法。

对象的运行时类型与变量或表达式的编译时类型之间存在重要区别。 表达式的编译时类型只能从其组件的编译时类型确定。 作为这些表达式的值的对象的运行时类型可以从表达式的参数的运行时类型确定,只要它们与编译时类型兼容即可。

为了说明这一点,在您的特定代码示例中:

  • 变量v具有编译时类型Parent ,但分配给它的值的运行时类型将为Child
  • 表达式v.getClass()将具有编译时类型Class<? extends Parent> Class<? extends Parent> (表示Parent类型或其子类之一的类对象。)。 它在运行时的值是Child.class ,类型为Class<Child>
  • 表达式v.getClass().cast(obj)将具有编译时类型Parent 它的运行时类型将是obj的运行时类型 ,因为它的运行时值实际上将是obj本身。 (也就是说,如果obj属于可分配给Child类型的变量的类型,否则cast()将抛出ClassCastException

我一直在寻找这个问题的答案,但我能找到的只是通用类型用法或关于反射的一般说明。

您收到Class<Parent>因为它是编译时类型。

//compiletime v is of type Parent
Parent v = new Child(); 
//The class of a Parent object is either the Parent class or a child Class
Class<? extends Parent> cls = v.getClass();
//The return type of cast is the at compile time known upper bound, here it is 
//Parent, which is true since every Child object is also a Parent object.  
cls.cast(...);
//Note that this will throw a runtime exception, since it will perform a 
//cast to child at runtime. The cast uses the Child class at runtime and
//fails for other instances of Parent.
cls.cast(new Parent());

这是一个简单的例子,您可以使用它。

class Test<T>{
  public Test(Class<T> cls){clazz = cls;}
  ArrayList<T> list = ...;
  Class<T> clazz;
  void add(Object o){
     list.add((T)o);//Cast does nothing at runtime
     list.add(clazz.cast(o)); //casts o to T
  }
}

形式(T)o的正常强制转换在java中不起作用,因为泛型类型T在运行时是未知的。 jvm只能看到永不失败的上界(Object)强制转换。 改为使用cast方法引用实际类是一种解决方法。

这是因为getClass()方法和泛型的设计。

出于兼容性原因,getClass()方法尚未生成泛型,因此它返回类型的实例

Class<?> 

Class<Child> 

正如你所料。

Class<?> 

表示类型参数为Object的泛型类型。

所以,返回类型

Class<?>.cast() 

方法是Object。 即这种方法的通用性质不起作用。

你可以写

v3 = ( (Class<Child>) v.getClass() ).cast(v2);

但这是没有意义的,因为你可以写

v3 = ( Child ) v.getClass().cast(v2);

此外,您应该记住,泛型只能在编译时工作。 即genercis仅用于IDE的类型检查。 在运行时,所有泛型都是

<?>

实际上,cast()方法在运行时不执行任何操作。 这只是在您拥有类型实例时使用的存根

Class<something>

暂无
暂无

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

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