【问题标题】:need for casting to a generic type in java需要在 java 中转换为泛型类型
【发布时间】:2013-08-21 12:55:46
【问题描述】:

在使用链表(实际上是内部类Node)实现优先级队列时,我将insert()max() 方法编码如下。它使用惰性方法保持项目无序,然后通过它们搜索仅当发生max()deleteMax() 调用时才用于最大元素。

public class LinkedListMaxPQ<Item extends Comparable<Item>>{
    private int N;
    private Node head;

   public void insert(Item item) {
       Node old = head;
       head = new Node();
       head.item = item;
       head.next = old;
       N++;
    }

    public Item max() {
        Item maxitem = (Item) this.head.item;
        for(Node t=head.next;t!=null;t=t.next){
            if(gt(t.item,maxitem)){
            maxitem = (Item) t.item;
            }
        }
        return maxitem;
    }
    private boolean gt(Comparable x,Comparable y){
    return x.compareTo(y) > 0;
}



   private class Node<Item extends Comparable<Item>>{
      Item item;
      Node next;
   }

}

我想知道为什么我需要 Item maxitem = (Item) this.head.item 中的演员表?由于该类使用泛型类型Item which extends Comparable,并且内部类也使用 Item extends Comparable ,因此人们会认为这样的转换是不必要的。

如果我省略演员表

Item maxitem = this.head.item;

编译器会报错类型不匹配

类型不匹配:无法从 Comparable 转换为 Item

有人可以解释为什么会这样吗?

【问题讨论】:

  • 因为不是Item是可以和Item比较的东西,不一样
  • Type erasure, overriding and generics 可能重复使用for(Node&lt;Item&gt; t=head.next;t!=null;t=t.next){ 将消除类型不匹配错误。

标签: java generics linked-list


【解决方案1】:

因为Java 将Item 视为Node 类声明中的类型参数(与LinkedListMaxPQ&lt;Item extends Comparable&lt;Item&gt;&gt; 中声明的Item 类型参数无关)。

此声明 -

private class Node<Item extends Comparable<Item>>{
    Item item;
    Node next;
}

告诉编译器你正在创建一个私有类,它有一个名为Item 的类型参数,它是Comparable&lt;Item&gt; 的子类型。在类型擦除期间,这个Item 将被它的边界替换,它的类型是Comparable。这就是您需要显式转换的原因。

另外,下面这行 -

private Node head;

创建一个原始类型Node,没有任何可用的类型信息。您应该会收到有关此行的警告。

要解决此问题,请按如下方式声明您的 head -

private Node<Item> head;

并通过以下方式创建一个实例 -

head = new Node<Item>();  // if you are using jdk 6 or lesser
head = new Node<>();  // if you are using jdk 7

以类似的方式更新所有Node 引用,您的警告应该会消失。

如果您需要进一步说明类型参数绑定,您可以阅读one of my blog posts,我已尝试解释类型参数绑定的工作原理。

【讨论】:

  • 问题不在于head 变量,而在于循环中的t
  • @JonathanDrapeau:它在所有节点声明中。我刚刚提供了上述声明作为示例,但如果您仍然坚持,我会更新我的答案。
  • 我不坚持,错误是因为t 的声明方式,而不是head 的方式。仅更改 head 并不能解决错误并回答问题。
  • @JonathanDrapeau:嗯,我已经提到了原始类型和它之前产生的问题。不管怎样,我希望现在没事。
【解决方案2】:

你需要

private class Node{
...

将其设置为:

private class Node<Item extends Comparable<Item>>{

您正在创建一个名为 Item 泛型类型,它与封闭类的 Item 类型相同,即使它具有相同的名称.

【讨论】:

    【解决方案3】:

    很简单,因为你在创建head的时候没有指定类型,node.head的类型是object

    这应该可以解决您的问题

    public class LinkedListMaxPQ<Item extends Comparable<Item>>{
        private int N;
        private Node<Item> head;
    
       public void insert(Item item) {
           Node<Item> old = head;
           head = new Node<Item>();
           head.item = item;
           head.next = old;
           N++;
        }
    
        public Item max() {
            Item maxitem =  this.head.item;
            for(Node<Item> t=head.next;t!=null;t=t.next){
                if(gt(t.item,maxitem)){
                maxitem =  t.item;
                }
            }
            return maxitem;
        }
    
    
    
       private class Node<Item extends Comparable<Item>>{
          Item item;
          Node<Item> next;
       }
    
    }
    

    【讨论】:

    • 问题不在于循环中的head变量,而是t
    • 我不同意你的观点,指定类型,正在解决描述的问题
    • 只声明head并不能消除错误,您需要更改t以消除Type mismatch错误。除非 Eclipse 搞错了……
    • 对于我刚刚上传的这段代码,eclipse 向我显示的obly 错误缺少方法gt
    【解决方案4】:

    正如@JonathanDrapeau 所指出的,答案很简单:将t 变量的声明更改为Node&lt;Item&gt;

        for (Node<Item> t = head.next; t != null; t = t.next){
            if (gt(t.item, maxitem)){
            maxitem = t.item;
            }
        }
    

    第二个选项:删除Node类定义中的类型参数,如果你想引用与父类LinkedListMaxPQ中相同的类型:

    public class LinkedListMaxPQ<Item extends Comparable<Item>> {
    
        ...
    
        private class Node {
            Item item;
            Node next;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-01
      • 2022-11-27
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多