Java 中的某些方法为什么要求传入一个 Class 对象
Java 中的某些方法為什么要求傳入一個 Class 對象
??在 Java 中,某些方法要求傳入一個 Class 對象,這能保證該方法能返回一個正確的類型的對象,從而免除返回后的強制類型轉換。比如 Spring 容器中的 getBean 方法,此方法有兩個常用的重載:
Object getBean(String name) throws BeansException;<T> T getBean(String name, Class<T> requiredType) throws BeansException;??這兩個方法中,其中有一個方法多了一個類型為 Class<T> 的參數,那么,多提供這個 Class<T> 參數的作用是什么呢?
??熟悉 Spring 的讀者應該很清楚,使用有 Class<T> 參數的 getBean 方法,可以免除之后的強制類型轉換。因為 Java 支持基類引用指向子類對象,但基類引用只能調用基類方法,這一點與此基類引用指向的是本基類對象還是子類對象無關。也就是說,基類引用無法調用子類名稱特有的方法(編譯會不通過),而很多方法都會返回 Object 類型,這意味著強制轉換經常是必要的。
??那么,為什么使用有 Class<T> 參數的方法可以做到這一點呢?或者說,如何通過傳遞 Class<T> 參數來使該方法能返回想要的類型呢?
??這可以通過設計這樣的一個函數來實現:
public static <T> T convertType(Object objToBeConverted, Class<T> convertedType) {return (T) objToBeConverted; }??這樣一來,強制類型轉換 (SomeClass)someObject 即可由調用此函數 convertType(someObject, SomeClass.class) 來替代了(設 SomeClass 為某類名。someObject 為 Object 引用類型,其指向 SomeClass 對象或其子類對象)。
??不過,要注意的是,上述自定義函數 convertType 的形參 Class<T> convertedType 中的 T,是基于靜態類型推斷得出的。如果傳入給形參 convertedType 的實參是動態生成的 Class 對象,則此處的 T 可能不是預想的值。例如:
public class Test {private static <T> T convertType(Object objToBeConverted, Class<T> convertedType) {System.out.println("函數 convertedType 被調用。其中,形參 convertedType:" + convertedType);System.out.println("");return (T) objToBeConverted;}public void fun(Test test) {System.out.println("Test 的函數 fun(Test test) 被調用。其中,形參 test:" + test.getClass());System.out.println("");}public static void main(String[] args) {System.out.println("");Test testExtends1 = new TestExtends();// 函數 convertedType 被調用。其中,形參 convertedType:class TestExtendsvar result1 = convertType(testExtends1, testExtends1.getClass());// TestExtends 的函數 fun(Test testExtends) 被調用。其中,形參 testExtends:class TestExtendsresult1.fun(result1);TestExtends testExtends2 = new TestExtends();// 函數 convertedType 被調用。其中,形參 convertedType:class TestExtendsvar result2 = convertType(testExtends2, testExtends2.getClass());// TestExtends 的函數 fun(TestExtends testExtends) 被調用。其中,形參 testExtends:class TestExtendsresult2.fun(result2);TestExtends testExtends3 = new TestExtends();// 函數 convertedType 被調用。其中,形參 convertedType:class TestExtendsvar result3 = convertType(testExtends3, TestExtends.class);// TestExtends 的函數 fun(TestExtends testExtends) 被調用。其中,形參 testExtends:class TestExtendsresult3.fun(result3);} }class TestExtends extends Test {@Overridepublic void fun(Test testExtends) {System.out.println("TestExtends 的函數 fun(Test testExtends) 被調用。其中,形參 testExtends:" + testExtends.getClass());System.out.println("");}public void fun(TestExtends testExtends) {System.out.println("TestExtends 的函數 fun(TestExtends testExtends) 被調用。其中,形參 testExtends:" + testExtends.getClass());System.out.println("");} }??可以看出,上述代碼中的對象 testExtends1 與 testExtends2 屬于同一類型 TestExtends,但由于它們分別被不同類型的引用所接收,通過各自的 getClass() 來動態生成類型,所以導致即便是函數 convertedType 的形參 convertedType 是正確的值,但函數 convertedType 中的 T 卻不正確。靜態推斷的結果是將 T 推斷為各自對象引用的類型,而不是各自對象自身真正的類型。因此,當調用函數 convertedType 時,應該像上面的 testExtends3 一樣,使用明確的類型 XXX.class 作為實參,而不是使用 Object 對象的方法 getClass() 。
??因此,對于本文開頭提及的方法,如果傳入類型為 Class<T> 的參數,該方法就能保證返回值類型為指定的類型。
總結
以上是生活随笔為你收集整理的Java 中的某些方法为什么要求传入一个 Class 对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 中,类、类对象、泛型之间的转换
- 下一篇: 为什么说 Java 是按值传递的?