簡體   English   中英

如果在編譯過程中將Java類型參數替換為其各自的邊界,為什么以下代碼不起作用?

[英]If Java type parameters are replaced with their respective bounds during compilation why the following code doesn't work?

class World{

  <T extends Class1> World(TreeSet<? extends ClassA> set){
    *some code*
  }

  <T extends Class2> World(TreeSet<? extends ClassB> set){
    *some code*
  }

}

上面的代碼顯示錯誤“名稱沖突:<T#1> World和<T#2> World具有相同的擦除”。 為什么代碼無法編譯? 更重要的是,為什么編譯器說它們具有相同的擦除? 我在該站點上發現的與該主題相關的所有問題都不會深入解釋我的問題。

我在包含以下方法的類上使用Intellij Idea的Bytecode Viewer插件檢查了問題:

public <A extends Calendar> void fn(ArrayList<? extends File> abc){  //line number:11
  A a=(A)new Object();  //line 12
}  //line number:13

以下是字節碼查看器中與此方法相對應的字節碼:

  // access flags 0x1
  // signature <A:Ljava/util/Calendar;>(Ljava/util/ArrayList<+Ljava/io/File;>;)V
  // declaration: void fn<A extends java.util.Calendar>(java.util.ArrayList<?extends java.io.File>)
public fn(Ljava/util/ArrayList;)V
  L0
    LINENUMBER 12 L0
    NEW java/lang/Object
    DUP
    INVOKESPECIAL java/lang/Object.<init> ()V
    CHECKCAST java/util/Calendar
    ASTORE 2
 L1
    LINENUMBER 13 L1
    RETURN
 L2
    LOCALVARIABLE this LMain; L0 L2 0
    LOCALVARIABLE abc Ljava/util/ArrayList; L0 L2 1
    // signature Ljava/util/ArrayList<+Ljava/io/File;>;
    // declaration: java.util.ArrayList<? extends java.io.File>
    LOCALVARIABLE a Ljava/util/Calendar; L1 L2 2
    // signature TA;
    // declaration: A
    MAXSTACK = 2
    MAXLOCALS = 3

看上面的第2行。 盡管已注釋掉,但保留了具有適當范圍的類型參數。 但是方法簽名在編譯后不包含任何類型參數(第4行)。 我們在第10行中再次看到保留的類型參數信息用於轉換,它對應於原始代碼的第12行。 因此得出的結論是類型參數並沒有被其邊界完全取代。 您的編譯文件將保留有關類型參數及其范圍的信息。 僅在編譯器確定需要時才使用此保留的信息。 出於某種原因,編譯器認為方法(或構造函數)不需要在編譯文件中的聲明中包含這些信息(這解釋了“相同擦除”錯誤部分)。 當它不具有通用功能時,其原因與對Java版本的向后兼容性有關。 因此,僅更改/添加/刪除類型參數和/或其邊界不會使方法或構造函數過載。


我知道我的回答很粗略,但據我所知並非錯誤。 請提出我在評論中缺少的任何內容,或發表您自己的答案。

暫無
暫無

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

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