簡體   English   中英

編譯時Java錯誤不明確

[英]Unclear Compile-time Java Error

我使用以下代碼在編譯時錯誤方面遇到了奇怪的行為(我正在使用JDK7):

public class classA { public void foo( List<Object> o ){} }

public class classB<T>{ public void bar( List<Object> o ){} }

我們考慮以下測試對象

List<String> o = new ArrayList<String>();

通過將o作為參數傳遞給類classA的方法foo ,沒有辦法讓java編譯,並且據我所知 ,應該沒有。

現在說我們在classB的主要方法中並嘗試調用bar而不實例化classB的實例來調用它。 我可能期望得到一個非靜態方法無法從靜態上下文編譯錯誤調用,就像我試圖在classA中拉它一樣,但我得到轉換調用錯誤。 這是有道理的 - 類型不排隊。

但是,如果我嘗試從非靜態上下文中調用bar,就像在

ClassB b = new classB(); 
b.bar( o );

Java似乎原諒我沒有排列類型並運行代碼沒問題。 我還沒有做任何事情來解決typcasting的問題,那么為什么Java讓這個代碼執行,而不是classA呢?

編輯:回答一些問題。 classA僅供參考 - 它不應該編譯,我不指望它,所以我不能提供編譯它的代碼。 可以通過以下方式給出編譯和執行的classB的代碼:

public class classB<T> {
    public void bar( List<Object> o ){}

    public static void main( String[] args ){ 
        classB b = new classB();
        List<String> o = new ArrayList<String>();
        b.bar( o );
    }

}

此代碼編譯並執行。 而不在類報關行的一般聲明完全相同的代碼不起作用。 我理解有人提到的類型擦除,但它是如何幫助的,因為T不是方法欄或主代碼中的引用

此外,還有很多方法可以使這些代碼更好。 我真的只是在尋找它的行為的解釋

將類定義為時

class ClassB<T>

但實例化為

new ClassB().bar(new ArrayList<String>());

你實際上使用的是原始類型(沒有泛型)版本。 如果您發現有關類型安全的警告; 方法簽名是bar(List)而不是bar(List<Object>)

類型安全:方法欄(List)屬於原始類型ClassB。 應參數化對泛型類型ClassB的引用。

如果將參數化類型T傳遞給,例如String

new ClassB<String>().bar(new ArrayList<String>());

它不會與錯誤一起編譯(再次注意方法簽名)

The method **bar(List<Object>)** in the type ClassB<String> is not applicable for the arguments (ArrayList<String>)

這是對泛型實現方式的限制。

他們是選擇加入的。

classB b = new classB();

在這里,你選擇退出泛型,你會收到警告。

Note: classB.java uses unchecked or unsafe operations.

當您選擇退出泛型類型檢查時,對於整個類,即使對於不使用綁定類型T方法,也不會獲得任何類型檢查。

正如@vandale指出的那樣,在關閉泛型的情況下,你甚至可以獲得編譯的代碼

 public void bar( List<Float> o );  

如果你做了

classB<Object> b = new classB<Object>();

它不會再編譯了。

請嘗試使用此代碼:

public void method(List<? extends Object> o) { /* body */ }

這樣它就會接受任何列表,其泛型類型參數是Object的后代,就像你想要的那樣。 :)

Java仍會產生“未經檢查”的警告,但由於擦除 ,它能夠編譯; 也就是說,List <T>和List <E>類型在Java虛擬機中使用相同的非泛型底層類型。 您可以將泛型視為僅用於在調用站點插入強制轉換的語法糖並進行一些額外的檢查,但在編譯器發出的字節碼中,就好像T和E被Object替換為無處不在,因此編譯器能夠將此視為警告而非錯誤。

暫無
暫無

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

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