簡體   English   中英

Java泛型GetThis技巧解釋

[英]Java Generics GetThis Trick Explanation

我正在閱讀Java Generics,我遇到了這個主題,我有點困惑。

來自: http//www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ205

public abstract class Node <N extends Node<N>>  {
   private final List<N> children = new ArrayList<N>();
   private final N parent;

   protected Node(N parent) {
     this.parent = parent;
     parent.children.add(this);  // error: incompatible types
   }
   public N getParent() {
     return parent;
   }
   public List<N> getChildren() {
     return children;
   }
 }

public class SpecialNode extends Node<SpecialNode> {
   public SpecialNode(SpecialNode parent) {
     super(parent);
   }
} 

滾動降低幾個屏幕......

public abstract class Node <N extends Node<N>>  {
   ...
   protected Node(N parent) {
     this.parent = parent;
     parent.children.add( (N)this ); // warning: unchecked cast
   }
   ...
 }

目標類型為類型參數的強制轉換無法在運行時驗證,並導致未經檢查的警告。 這種不安全的演員引入了意外的ClassCastException的可能性,最好避免。

有人能給我一個例子,上面的代碼拋出ClassCastException嗎?

謝謝。

第一個代碼示例

在第一個代碼示例中,存在編譯錯誤。 您可以在IDE中自行驗證。

我說: The method add(N) in the type List<N> is not applicable for the arguments (Node<N>)

問題是N是Node的子類型。 N的列表可能是StupidNode的列表,其中StupidNode是Node的子類。 但是當前實例可能不是StupidNode,它可能是Node的不同子類,因此添加它可能是錯誤的


第二個代碼示例

現在第二個代碼示例是一個開發人員,他厭倦了他不理解的編譯時錯誤,認為編譯器是錯誤的並試圖強制轉換。 這樣的強制轉換會使代碼編譯,但可能會在相同條件下在運行時中斷 (如上所述)。

因此,編譯器會發出警告,以幫助您了解某些內容可能出錯。


樣品問題

對於前面的兩個代碼示例,如果調用代碼寫入(對於Node兩個子類NodeANodeB ),則可能會發生此問題:

Node<NodeA> root = new NodeA<NodeA>(null); 
// code needs a change, to be able to handle the root, that has no parent
// The line with parent.children will crash with a NullPointerException
Node<NodeB> child = new NodeB<NodeB>(root);

在第二行,將在Node的構造函數中運行的代碼將解釋為(用當前參數NodeB替換格式參數N ):

public abstract class Node <NodeB>  {
   private final List<NodeB> children = new ArrayList<NodeB>();
   private final NodeB parent;

   protected Node(NodeB parent) {
     this.parent = parent;
     parent.children.add(this);  // error: incompatible types
   }
  // ...
 }

如您所見,調用者的第二行將傳遞NodeA實例,而Node的構造函數需要NodeB 因此錯誤......


注釋要求的更新 :子類NodeA(或NodeB)的示例代碼。

public class NodeA extends Node<NodeA>  {
   public NodeA(NodeA parent) {
     super(parent);
   }
}

暫無
暫無

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

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