簡體   English   中英

為什么instanceof有時似乎可以在靜態泛型函數中工作?

[英]Why does instanceof seem to work in a static generic function sometimes?

問候。 這是我在本網站的第一篇文章。

我以為是因為類型擦除 ,所以不能期望下面的代碼可以編譯,實際上,它不能在早期版本的Eclipse上編譯。 我的理解是instanceof是一個運行時運算符,並且不知道在運行時會被編譯掉的泛型類型:

   public static <E extends Comparable<? super E>> 
   void SampleForQuestion(E e)
   {
      if ( !(e instanceof String) )
         System.out.println("I am not a String");
      else
         System.out.println("I am  a String");
   }

但是,我很驚訝地看到您的一個線程實際上在答案中包含了這樣的代碼,而我最新的Eclipse(Windows上的JVM 1.6 rev 20上的Galileo)對此非常滿意,並且它也可以工作。 (我確實注意到有人說它可以在Eclipse上運行,但不能在該線程的另一個IDE / JDK中運行,但不記得具體細節。)

有人可以解釋它為什么起作用,更重要的是,因為我必須指導我的學生,是否應該期望它將來能起作用?

謝謝。 (我希望代碼格式正確通過-從我的角度看,它看起來正確地縮進了,並且沒有制表符。)

擦除的是E 實際上,您不能執行if (e instanceof E) ,因為類型參數E被刪除了。 但是, String不是參數化類型, e確實具有運行時類型,因此if (e instanceof String)可以正常工作。

JLS 15.20.2類型比較instanceof運算符

 RelationalExpression: RelationalExpression instanceof ReferenceType 

instanceof運算符的RelationalExpression操作數的類型必須是引用類型或null類型; 否則,將發生編譯時錯誤。 instanceof運算符后面提到的ReferenceType必須表示一個引用類型。 否則,將發生編譯時錯誤。 如果在 instanceof 運算符 之后提到 ReferenceType 不表示可驗證的類型 (第4.7節) ,則是編譯時錯誤

String是可更改的類型。 E不是。

JLS 4.7可更改類型

由於在編譯過程中會擦除某些類型信息,因此並非所有類型在運行時都可用。 在運行時完全可用的類型稱為可更改類型。 僅當以下條件之一成立時,類型才是可更改的:

  • 它指的是非泛型類型聲明。
  • 這是一個參數化類型,其中所有類型參數都是無界通配符
  • 這是原始類型。
  • 它是原始類型。
  • 它是一種數組類型,其組件類型是可更改的。

也可以看看

很好 接受E e的方法被編譯為Comparable e ,但這並不能防止對運行時存在的類型進行檢查(示例中為String )。 您不能執行的操作是檢查ArrayList<String> (或您自己的類的通用專業化),因為ArrayList類型在運行時存在,但ArrayList<String>不存在。 因此,人們使用黑客手段,例如檢查列表的第一個元素。

小寫的e是一個對象,每個對象都有它的類型。 您可以在任何對象上檢查instanceof。 閱讀不同名稱的代碼,將更容易獲得:

   public static <E extends Comparable<? super E>> 
   void SampleForQuestion(E paramObject)
   {
      if ( !(paramObject instanceof String) )
         System.out.println("I am not a String");
      else
         System.out.println("I am  a String");
   }

暫無
暫無

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

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