Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 方法在重写的JTable中的构造函数之前调用_Java - Fatal编程技术网

Java 方法在重写的JTable中的构造函数之前调用

Java 方法在重写的JTable中的构造函数之前调用,java,Java,我有一个扩展JScrollPane的类,它创建了另一个扩展JTable的类的对象。基本上是这样的: class CustomScrollPane{ private CustomTable table public CustomScrollPane(..){ table = new CustomTable(this); .. } public void scrollToBottom(){ ... } } 在CustomTable类别I中,重

我有一个扩展JScrollPane的类,它创建了另一个扩展JTable的类的对象。基本上是这样的:

class CustomScrollPane{
   private CustomTable table

   public CustomScrollPane(..){
   table = new CustomTable(this);
   ..
   }
   public void scrollToBottom(){
      ...
   }
}
在CustomTable类别I中,重写tableChanged:

public class CustomTable extends JTable{

private CustomScrollPane scrollPane;

public CustomTable(CustomScrollPane scrollPane){
    super();
    this.scrollPane = scrollPane;
}

@Override
public void tableChanged(TableModelEvent e) {
    super.tableChanged(e);
    scrollPane.scrollToBottom();
}
当我运行这个程序时,在tableChanged()的scrollPane上会出现一个NullPointerException,这怎么可能呢?在构造函数中设置scrollPane时,scrollPane如何可以为null?在调试器中运行它表明tableChanged()在构造函数之前被调用。添加条件

     if (scrollPane != null)
实际上解决了这个问题,因为稍后会调用构造函数。此外,将JTable定义为其构造的,如:

        table = new JTable(){
        @Override
        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            final Component c = super.prepareRenderer(new CustomTableCellRenderer(), row, column);
            if (c instanceof JComponent){
                ((JComponent) c).setOpaque(true);
            }
            return c;
        }

        @Override
        public void paint(Graphics g) {
            int scrolling = scrollPane.getViewport().getViewPosition().y;
            super.paint(g);
            g.drawImage(image.getImage(), -30, -50 + scrolling, null, null);
        }

        @Override
        public void tableChanged(TableModelEvent e) {
            super.tableChanged(e);
            scrollPane.scrollToBottom();
        }
    };

直接在CustomScrollPane构造函数中也可以工作。为什么不能将其拆分为一个单独的类?

这是一种典型的非常糟糕的模式,即部分初始化的实例脱离了构造函数的作用域

我猜CustomScrollPane在调用新的CustomTable时会向CustomTable触发一些事件(如下所示)

由于滚动窗格尚未初始化,因此您将获得NPE


千万不要让事情逃出构造函数,这样你就安全了。

这是典型的非常糟糕的模式,部分初始化的实例逃出了构造函数的作用域

我猜CustomScrollPane在调用新的CustomTable时会向CustomTable触发一些事件(如下所示)

由于滚动窗格尚未初始化,因此您将获得NPE


千万不要让东西逃逸构造函数,这样你就安全了。

它看起来像是
JTable
构造函数调用方法
tableChanged(…)
——这意味着它是在你能够初始化
滚动窗格
实例变量之前被调用的

首先,我建议你看看书中的一些谜题——特别是谜题51:重点是什么,也许谜题53:做你自己的事。他们应该帮助你了解发生了什么。基本上,
CustomTable
构造函数的第一行调用
JTable
构造函数(通过
super()
)。
JTable
构造函数正在尝试调用已被覆盖的
tableChanged
。被覆盖的
表已更改
尝试操作
滚动窗格
。。。但是所有这些都发生在构造函数的第1行(
super()
)-在执行第
this.scrollPane=scrollPane
行之前,因此
scrollPane
仍然为空

接下来,我建议使用。这里有两个对象—滚动窗格和自定义表—当另一个对象发生更改时,需要通知其中一个对象。这是教科书上的观察者模式。以下是大概的想法:

文件
CustomTable.java

它看起来像是
JTable
构造函数调用了方法
tableChanged(…)
——这意味着它是在您能够初始化
滚动窗格
实例变量之前被调用的

首先,我建议你看看书中的一些谜题——特别是谜题51:重点是什么,也许谜题53:做你自己的事。他们应该帮助你了解发生了什么。基本上,
CustomTable
构造函数的第一行调用
JTable
构造函数(通过
super()
)。
JTable
构造函数正在尝试调用已被覆盖的
tableChanged
。被覆盖的
表已更改
尝试操作
滚动窗格
。。。但是所有这些都发生在构造函数的第1行(
super()
)-在执行第
this.scrollPane=scrollPane
行之前,因此
scrollPane
仍然为空

接下来,我建议使用。这里有两个对象—滚动窗格和自定义表—当另一个对象发生更改时,需要通知其中一个对象。这是教科书上的观察者模式。以下是大概的想法:

文件
CustomTable.java

您确定在CustomScrollPane或CustomTable中没有另一个实际被调用的构造函数吗?再次运行调试器,查看CustomTable中的哪个构造函数是从CustomScrollPane中的哪个构造函数调用的。是的,我想你是对的。它似乎调用了JPanel中的其他构造函数,我觉得这有点奇怪,因为该构造函数,不管它是什么,都不可能具有与我相同的参数(我自己类的对象)。您确定在CustomScrollPane或CustomTable中没有另一个实际被调用的构造函数吗?再次运行调试器,查看CustomTable中的哪个构造函数是从CustomScrollPane中的哪个构造函数调用的。是的,我想你是对的。它似乎调用了来自JPanel的其他构造函数,我觉得有点奇怪,因为这个构造函数,不管它是什么,都不可能有和我相同的参数(我自己类的对象)。我不确定我是否理解你的建议。你认为我应该删除table=newcustomtable(这个);从构造函数中添加一个setTable()方法?请看下面的答案,它非常详细地描述了我的观点。我不确定我是否理解你的建议。你认为我应该删除table=newcustomtable(这个);从构造函数中添加一个setTable()方法?请看下面的答案,它非常详细地描述了我的观点感谢构造函数信息、链接和模式建议!感谢构造器信息、链接和模式建议!
public class CustomTable extends JTable {

    // No more scroll pane; only observers
    private List<ChangeListener> listeners = [];

    // no more scroll pagne
    public CustomTable(){
        super();
    }

    @Override
    public void tableChanged(TableModelEvent e) {
        super.tableChanged(e);
        this.fireChangeEvent();
    }

    /* new methods */

    public void addChangeListener(ChangeListener listener) {
        listeners.add(listener);
    }

    public void removeChangeListener(ChangeListener listener) {
        // ...
    }

    private void fireChangeEvent() {
        for(String l : listeners ){
            l.onChange();
        }
    }
}
class CustomScrollPane implements ChangeListener{
   private CustomTable table

   public CustomScrollPane(/*...*/){
       table = new CustomTable();
       table.addChangeListener(this);
       //...
   }

   public void scrollToBottom(){
      //...
   }

   /* new methods */

  @Override
  public void onChange() {
      scrollToBottom();
  }
}