簡體   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