簡體   English   中英

Java Generics - 類型聲明

[英]Java Generics - type declaration

class Response<T>
{ ... }

Response response = new Response();

上面的代碼編譯。 我不明白隱含的是什么。 編譯器不應該要求'T'的類型規范嗎? 例如以下內容:

Response<String> response = new Response<String>(); 

從技術上講,它應該/應該。 但是,為了向后兼容Java 5,這沒有完成,因此不需要通用參數。 而且由於泛型是通過擦除實現的,所以無論你是否聲明參數,所發出的字節碼都是相同的 - 你所缺少的只是一些編譯時檢查。

(請注意,如果在response對象上調用方法,編譯器將警告您使用“原始類型”,這意味着您以非泛型方式使用泛型類,因此它不能強制執行任何約束。您。)

編輯:關於向后兼容性,這是一種平衡行為,並且Sun明顯犧牲了一些方面來改進/維護其他方面。 打破向后兼容性將是一件非常重要的事情 - 這意味着遷移到最新版本的Java將是一個非常重要的項目,並且會在企業內部產生更大的阻力來升級。

這里的重大決定是通過擦除來實現泛型,這樣它們就是“僅編譯時”構造,並且生成的字節碼與先前版本相同。 這樣做的好處是,例如1.5 java.util.HashMap仍然可以用1.4編寫的代碼訪問(當然這個優點也可以擴展到你自己的類)。 但是,有很多觀點,特別是那些習慣使用類似技術的其他語言中的仿制葯,這不是最好的決定,並且削弱了仿制葯的實用性。 我不會在這里談論它。

至於它是否顛覆了編譯器想要強制執行的檢查; 我認為這並不像你想象的那么糟糕。 是的 ,您可以編寫代碼,使編譯器不進行任何泛型檢查,並且您可以故意破壞預期的語義。 但是,編譯時檢查並不是某種安全功能,它們只是幫助您,作為一種靜態分析形式,可以獲取某些類型的錯誤。 如果你顛覆它們,請隨意這樣做。 但是如果你正確編寫了通用類,那么你將得到你想要的編譯時檢查。

特別是因為編譯器(可以)給你關於原始類型的警告,所以有一個明確的升級路徑從1.4到5.升級你的JDK - 你的舊代碼仍然編譯,盡管有警告。 然后使用這些警告來追蹤違規行為,並在需要時生成舊代碼。 在我看來,這比簡單地拒絕編譯舊的(可能是功能性的!)代碼要好得多,直到每個語句都添加了適當的泛型。

大多數IDE都允許您對不同警告類型的嚴重性進行分類,這樣,如果您從頭開始開發Java 5應用程序,則可以告訴它將所有原始類型警告視為完全停止構建錯誤。

這稱為原始類型 你應該能夠打開警告讓它向你抱怨 - 聽聽那些警告。

例如,這是我跑步時得到的

javac -Xlint Test.java

使用您的代碼(將原始類型引用包裝到Test類中):

C:\Users\Jon\Test>javac -Xlint Test.java
Test.java:7: warning: [rawtypes] found raw type: Response
    Response response = new Response();
    ^
  missing type parameters for generic class Response<T>
  where T is a type-variable:
    T extends Object declared in class Response
Test.java:7: warning: [rawtypes] found raw type: Response
    Response response = new Response();
                            ^
  missing type parameters for generic class Response<T>
  where T is a type-variable:
    T extends Object declared in class Response
2 warnings

如果您此刻沒有這些警告,我建議您盡一切努力在您的環境中查看它們。 這取決於您正在使用的IDE /編譯器,但如果您找不到相關設置,請告訴我們您使用的是哪一個,我相信有人能夠為您找到它。

有關更多信息,請參閱Angelika Langer的Java Generics FAQ的原始類型部分

我認為通過不在底線中指定模板類,您將使編譯器自動替換Object類型。 這沒有錯,它在執行類型方面不是很有效。

這將編譯好。 如果不是,那么遺留代碼就會出現問題。 例如,由於HashMap現在被聲明為HashMap<K, V> ,您將如何處理聲明(未參數化)hashmap的所有代碼?

您只會在嘗試使用參數化值時收到錯誤:

class Response<T>
{ public T get()... }

String s= new Reponse().get(); //breaks - or requires a cast
String s= new Response<String>().get();

暫無
暫無

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

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