0

我欣喜若狂地说,几周前我刚刚在一个项目中实现了一个通用链表,而且可以工作了!不过有一个问题。我被迫做演员(没想到)。

以下是一些片段,我希望足以定义问题,从通用堆栈开始:

    public class GenericStack<E> {

      public LinkedList <E> stack = new LinkedList<>();

      public void push (E obj){
        stack.add(obj);
      }

      public E pop() {
        if (stack.isEmpty()) return null;
        return stack.removeLast();
      }
      ...
}

这是我使用通用堆栈的类定义:

public class Grid extends GenericStack<JTextField> implements ActionListener, KeyListener, KeyCodes

这是我的定义stack以及我正在推动和弹出的内容:

  GenericStack stack = new GenericStack();
  public static JTextField[][] cells = new JTextField[11][11];

这是我推进stack

 stack.push(Grid.cells[currentCell.row][currentCell.col]);

这是我弹出的地方stack,,只有在我显示的 CAST 时才有效:

  private void calculate(){
    JTextField w = new JTextField();
    while(stack.size()>0){
      w =  (JTextField) stack.pop();
      System.out.println("stack element " + w.getText());
    }
  }

现在我没有抱怨;我什至不确定是否存在要处理的问题,但是如果没有演员表(JTextField),我会得到“不兼容的类型--需要:JTextField; 找到:对象”,但stack.pop()明确定义为返回泛型类型,即JTextField,那我为什么要需要投吗?

4

3 回答 3

4

这就是问题:

GenericStack stack = new GenericStack();

那是使用原始类型GenericStack. 当您已经GenericStack<JTextField>诚实地扩展时,尚不清楚为什么您会得到这个。我希望你要么使用组合:

public class Grid implements ActionListener, KeyListener, KeyCodes {
    private final GenericStack<JTextField> stack = new GenericStack<JTextField>();

    private void calculate() {
        while (stack.size() > 0) {
            JTextField w = stack.pop();
            System.out.println("stack element " + w.getText());
        }
    }
}

使用继承:

public class Grid extends GenericStack<JTextField> 
    implements ActionListener, KeyListener, KeyCodes {

    private void calculate() {
        while (size() > 0) {
            JTextField w = pop();
            System.out.println("stack element " + w.getText());
        }
    }
}

目前你正在混合两者,这真的很奇怪。

于 2013-10-11T21:18:52.630 回答
1

您在以下实例化中使用了泛型类型的原始类型:

GenericStack stack = new GenericStack();  

当你使用原始类型时,类中的所有泛型类型都被它们的原始类型对应物替换,类型参数被它们的擦除替换。E因为在你的情况下擦除是Object, 因为它没有任何限制。所以,链表和方法:

public LinkedList <E> stack = new LinkedList<>();
public void push (E obj) { ... }
public E pop() { ... }

将被擦除为:

public LinkedList stack = new LinkedList();
public void push(Object obj) { ... }
public Object pop() { ... }

因此,Object当您调用pop()方法时,您会返回类型。

您需要的是参数化实例化

GenericStack<JTextField> stack = new GenericStack<>();

当然,JonSkeet 在他的回答中所说的话。不要混淆继承和组合。您有 type 的引用GenericStack,并且还对其进行了扩展。这没有意义。遵循乔恩回答中的建议。

于 2013-10-11T21:18:42.883 回答
0

哦!

很高兴它起作用了,我忽略了一些明显(对于有经验的人)的事情(我真的没有理由忽略),所以是的,我做出了 Rohit Jain 建议的改变(在注意到 Jon Skeet 之后),我有一个更时尚的爆破方法:

  private void calculate(){
    while(stack.size()>0){
      System.out.println("stack element " + stack.pop().getText());
    }
  }

(调用方法是calculate因为它很快就会这样做。)

但是,乔恩,我看不出我的代码如何表明我正在混合组合和继承,但也许那是因为我现在也没有完全理解!

不过,我会告诉你这一点:每天(一整天??)仅仅为了再写一行代码而感到沮丧已经结束了。爪哇摇滚!(一旦你达到了学习曲线上的某个点!)我对我在短短几天内取得的进展感到震惊!(好吧,也许咖啡有帮助!)

于 2013-10-11T21:40:34.997 回答