簡體   English   中英

在泛型方法和泛型類中鍵入推斷

[英]Type inference in generic method & generic class

無法理解Java中的泛型編程。

我讀了一些關於它的教程,但仍然很困惑,特別是當事情變得復雜時。

誰能解釋一下這個例子中發生了什么?

import java.util.Date;

public class Test1 {

    public static void main(String[] args) {
        P<Cls> p = new P<>();   //<1>   //I expect a ClassCastException here, but no. Why? //How does the type inference for class P<E> work? 
        System.out.println(p.name); //it prints
//      System.out.println(p.name.getClass());//but this line throws ClassCastException //why here? why not line <1>?

        test1(p);//it runs
//      test2(p);//throws ClassCastException//What is going on in method test1&test2? 
                //How does the type inference for generic methods work in this case?
        }


    public static<T> void test1(P<? extends T> k){
        System.out.println(k.name.getClass());
    }

    public static<T extends Cls> void test2(P<? extends T> k){
        System.out.println(k.name.getClass());
    }
}

class P<E>{
    E name = (E)new Date();//<2>
}

class Cls{}
P<Cls> p = new P<>();

請記住,Java通過擦除來實現泛型,這意味着P的構造函數實際上並不知道E在運行時是什么 Java中的泛型純粹是為了在編譯時幫助開發人員。

這意味着當您創建一個new P<>() ,會創建一個new Date()但它實際上並沒有轉換為任何特定類型,因為運行時對E沒有任何了解 E在運行時不存在,只要P<E>類而言。 name只是一個內部有DateObject引用。 但是,每當您編寫以運行時環境需要知道它是特定類型(在本例中為Cls )的方式使用name代碼時,編譯器會在不告訴您的情況下將強制轉換插入該類型。

  • p.name.getClass()被編譯為((Cls)p.name).getClass() ,它將創建一個類((Cls)p.name).getClass()異常。
  • test2()指定非泛型的類型約束( extends Cls )。 因此,它對p.name.getClass()調用同樣被轉換為((Cls)p.name).getClass()

另一方面:

  • System.out.println(p.name)實際上與System.out.println((Object)p.name)相同,因為println是一個采用object的非泛型方法。
  • test1(p.name)類似。 因為運行時實際上並不知道T是什么類型,所以它在調用getClass()之前基本上將p.name強制轉換為Object

換句話說,這是你的代碼,因為它實際上被編譯:

class P{
    Object name = new Date();
}

public static void main(String[] args) {
    P p = new P();   
    System.out.println(p.name);
    System.out.println(((Cls)p.name).getClass());

    test1(p);
    test2(p);
}


public static void test1(P k){
    System.out.println(k.name.getClass());
}

public static void test2(P k){
    System.out.println(((Cls)k.name).getClass());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM