简体   繁体   English

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

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

I hope you can assist me on this matter. 我希望你能帮助我解决这个问题。

I've been looking for answers to this question but all I could find was related to generic type usage or general instructions about reflection. 我一直在寻找这个问题的答案,但我能找到的只是通用类型用法或关于反射的一般说明。

Say we have a parent class and a child class which extends that parent. 假设我们有一个父类和一个扩展该父类的子类。 So, see below: 所以,见下文:

Parent v = new Child();

If I make v.getClass() it returns Child . 如果我创建v.getClass()它返回Child However, if I make v.getClass().cast() it returns an object from type Parent . 但是,如果我创建v.getClass().cast()它将从类型Parent返回一个对象。

Anyone knows why it happens? 谁知道为什么会这样? I also took a look at the Java API documentation and couldn't find a reason... 我还看了一下Java API文档,找不到原因......

Thanks for any thoughts. 谢谢你的任何想法。

There's an important distinction between what the runtime type of an object and the compile-time type of a variable or expression is. 对象的运行时类型与变量或表达式的编译时类型之间存在重要区别。 The compile-time type of an expression can only be determined from the compile-time types of its components. 表达式的编译时类型只能从其组件的编译时类型确定。 The runtime types of objects that are the values of these expressions may be determined from the runtime types of the parameters of the expression, as long as they are compatible with the compile-time types. 作为这些表达式的值的对象的运行时类型可以从表达式的参数的运行时类型确定,只要它们与编译时类型兼容即可。

To illustrate this, in your specific code sample: 为了说明这一点,在您的特定代码示例中:

  • The variable v has the compile-time type Parent , but the runtime type of the value assigned to it will be Child . 变量v具有编译时类型Parent ,但分配给它的值的运行时类型将为Child
  • The expression v.getClass() will have the compile-time type Class<? extends Parent> 表达式v.getClass()将具有编译时类型Class<? extends Parent> Class<? extends Parent> (a class object representing either the Parent type or one of its subclasses.). Class<? extends Parent> (表示Parent类型或其子类之一的类对象。)。 Its value at runtime will be Child.class which is of type Class<Child> . 它在运行时的值是Child.class ,类型为Class<Child>
  • The expression v.getClass().cast(obj) will have the compile-time type Parent . 表达式v.getClass().cast(obj)将具有编译时类型Parent It's runtime type will be the runtime type of obj , because its runtime value will, in fact, be obj itself. 它的运行时类型将是obj的运行时类型 ,因为它的运行时值实际上将是obj本身。 (That is, if obj is of a type that's assignable to a variable of type Child , otherwise cast() will throw a ClassCastException ) (也就是说,如果obj属于可分配给Child类型的变量的类型,否则cast()将抛出ClassCastException

I've been looking for answers to this question but all I could find was related to generic type usage or general instructions about reflection. 我一直在寻找这个问题的答案,但我能找到的只是通用类型用法或关于反射的一般说明。

You receive a Class<Parent> as that is the compile time type. 您收到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());

Here a simplified example for what you can use it. 这是一个简单的例子,您可以使用它。

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
  }
}

A normal cast in the form (T)o does not work in java as the generic type T is not known at runtime. 形式(T)o的正常强制转换在java中不起作用,因为泛型类型T在运行时是未知的。 The jvm only sees the upper bound (Object) cast which never fails. jvm只能看到永不失败的上界(Object)强制转换。 Using the cast method with a reference to the actual class instead is a workaround for this. 改为使用cast方法引用实际类是一种解决方法。

This is because of design of getClass() method and generics. 这是因为getClass()方法和泛型的设计。

For compatibility reasons, getClass() method have not made generic, so it returns instance of type 出于兼容性原因,getClass()方法尚未生成泛型,因此它返回类型的实例

Class<?> 

not

Class<Child> 

as you could expect. 正如你所料。

Class<?> 

means generic type with type parameter of Object. 表示类型参数为Object的泛型类型。

So, the return type of 所以,返回类型

Class<?>.cast() 

method is Object. 方法是Object。 Ie generic nature of this method does not work. 即这种方法的通用性质不起作用。

You can write 你可以写

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

but this is senseless since you can just write 但这是没有意义的,因为你可以写

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

Also, you should remember, that generics work only at compile time. 此外,您应该记住,泛型只能在编译时工作。 Ie genercis are only for type checking at your IDE. 即genercis仅用于IDE的类型检查。 At runtime all generics are 在运行时,所有泛型都是

<?>

So, actually, cast() method does nothing at runtime. 实际上,cast()方法在运行时不执行任何操作。 This is only a stub to use when you have instances of type 这只是在您拥有类型实例时使用的存根

Class<something>

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

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