簡體   English   中英

返回類型是擦除的一部分嗎?

[英]Is return type part of the erasure?

有人可以解釋為什么第二類不編譯?

1使用javac和JDK 6編譯好(Eclipse會抱怨此代碼)

public class SameSignatureMethods {
    public <T extends String> Boolean test()
    {
        return true;
    }

    public <T extends Character> Double test() 
    {
        return 1d;
    }
}

2對該示例稍作更改,編譯失敗,並出現以下錯誤:

name clash: <T>test() and <T>test() have the same erasure

唯一的變化是方法的返回類型:

public class SameSignatureMethods {
    public <T extends String> Boolean test()
    {
        return true;
    }

    public <T extends Character> Boolean test() {
        return true;
    }
}

這就是第一類的主要方法看起來如何:

public static void main(String[] args) {
    SameSignatureMethods m = new SameSignatureMethods();
    System.out.println("m.<Character>test()=" + m.<Character>test());
    System.out.println("m.<String>test()=" + m.<String>test());
}

因此,JDK編譯器編譯第一個版本但不編譯第二個版本,而Eclipse編譯器編譯兩個版本中的任何一個版本。

從Java字節代碼的角度來看,第一個版本包含兩種不同的方法(在類型擦除之后),即public java.lang.Boolean test()public java.lang.Double test() ,這是完全有效的。 當您覆蓋泛型方法時,JDK編譯器和Eclipse編譯器有時會生成此類方法,但這些方法隨后會標記為合成橋接方法。

第二個版本將包含兩個具有相同簽名的方法(在類型擦除之后),這在Java字節代碼中是不允許的。 因此JDK編譯器無法生成這樣的類文件。 我剛剛使用十六進制編輯器編輯了一個類文件來創建一個具有這些方法的類,並且在啟動程序時,我收到此錯誤:

Exception in thread "main" java.lang.ClassFormatError: Duplicate method name&signature in class file SameSignatureMethods
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(Unknown Source)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$000(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: SameSignatureMethods.  Program will exit.

我開始的課程看起來像這樣。 我使用String和Double因為它們具有相同的名稱長度:

public class SameSignatureMethods {
    public  <T extends String> String test() {
        return null;
    }

    public  <T extends Double> Double test() {
        return null;
    }

    public static void main(String[] args) {
        System.out.println(new SameSignatureMethods().<Double>test());
    }
}

然后,使用十六進制編輯器,我將第一個方法的簽名更改為public <T extends String> Double test() ,在類文件的兩個位置,一個帶有原始簽名()Ljava/lang/Double; ,一個帶有通用簽名<T:Ljava/lang/String;>()Ljava/lang/Double;

聽起來你已經成功地混淆了你的編譯器:

  • 返回類型不是簽名的一部分。 編譯器不能使用返回類型來告訴調用哪個方法。

  • 在您的示例中,無論如何,填充到方法簽名中的泛型函數不會影響返回類型。

  • 另外說<T extends String>毫無意義,你不能擴展最終類型。 (嗯,這只是一個警告,它不會停止編譯)

你想知道為什么第二個類不編譯,我想知道為什么第一個類編譯。 按原樣,第一類編譯,盡管有警告。 取出尖括號的東西會導致出現“重復方法”錯誤,無論如何都應該出現。 必須是編譯器錯誤。

在第一個類( SameSignatureMethods )中,運行時的2個方法分別返回BooleanDouble 在第二個類中,方法都返回Boolean

方法定義前面的<T extends String>並不意味着它是一個返回類型。

也許你想做這樣的事情:

public <T extends String> T test()
{
    return obj;// obj could be a String
}

但是,泛型類型在運行時被擦除,並且上面的方法將變為

public Object test()
{
    return obj;// obj could be a String
}

暫無
暫無

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

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