不知异常是否如下:
java.lang.NullPointerException
at test.getRowCount(Untitled1.java:33)
at javax.swing.table.DefaultTableModel.setDataVector(Unknown Source)
at javax.swing.table.DefaultTableModel.<init>(Unknown Source)
at javax.swing.table.DefaultTableModel.<init>(Unknown Source)
at javax.swing.table.DefaultTableModel.<init>(Unknown Source)
at test.<init>(Untitled1.java:18)
at Untitled1.main(Untitled1.java:13)
Exception in thread "main" 这是一个调用先后的问题,当你使用如new test()这样的方法的时候,它会调用test类的构造函数,由于没有定义其构造函数,就会调用其父类的构造函数,而且它的调用顺序如下:test() {
  super();  // 如果在类里面有默认变量初始化则会在super()后面运行。  // other method}
下面来看看在DefaultTableModel的构造方法,虽几经周转,却使用到了getRowCount()方法,而且在其中定义为:
    public int getRowCount() {
        return dataVector.size();
    }
而你在test类中重载了这个方法,它的返回值需要value的初始化,但它这时还没有初始化;但如果value改用static属性,则这个变量的初始化在对象实例化之前。最后有一点要说明:就是虽然我们在使用DefaultTableModel时可能比生成AbstractTableModel更加简单,但其用法不太理想,主要是因为它生成自己的对单元数据的引用,这个引用就是dataVector中所定义的内容。这种方法不仅缺乏灵活性和伸缩性,而且还会使编辑问题复杂化。这是由于它要求引用每个项目,所以只要使用模型,所有的数据都应在内存中,而无法按需响应数据检索请求。因此,我们通常改用其父类AbstractTableModel来定义一个表格模式。
PS:最最后的一点,在主窗口frame显示之前,需要定义它默认的关闭动作,这样才会使应用程序正常退出,代码如下:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

解决方案 »

  1.   

    还有一点要补充,就是要学会看nested exception,也就是递归异常的写法,它总是把离出现异常最近的内容写在异常信息的最前面,即它在代码的第十三行main中出现了异常(Untitled1.main(Untitled1.java:13));而它所调用的是test的构造方法(test.<init>(Untitled1.java:18)
    ),这个异常出现在Untitled1.java的第十八行;然后是三个DefaultTableModel的初始化方法(javax.swing.table.DefaultTableModel.<init>(Unknown Source)),你应该注意到,它的调用分别是指(在DefaultTableModel.java中定义的):
        public DefaultTableModel() {
            this(0, 0);
        }
        public DefaultTableModel(int rowCount, int columnCount) {
            this(newVector(columnCount), rowCount); 
        }
        public DefaultTableModel(Vector columnNames, int rowCount) {
            setDataVector(newVector(rowCount), columnNames);
        }
    它们依次调用,最后到了setDataVector方法中;
    而这个方法是这样的:
        public void setDataVector(Vector dataVector, Vector columnIdentifiers) {
            this.dataVector = nonNullVector(dataVector);
            this.columnIdentifiers = nonNullVector(columnIdentifiers); 
    justifyRows(0, getRowCount()); 
            fireTableStructureChanged();
        }
    它会调用DefaultTableModel的getRowCount()方法;
    最后,它调用了test类中的getRowCount()方法,空指针就出现了。
      

  2.   

    new test() 执行的过程:对于你写的程序 首先调用父类 DefaultTableModel()-〉DefaultTableModel(0, 0)-〉... -〉setDataVector() -> getRowCount()好了,程序执行到这步的时候,发现你overwrite getRowCount(),这样程序会执行你写的这个函数,但是此时你的private String[][] value并没有初始化,仍然为null,于是出现异常
      

  3.   

    忘了说一句,我把你的package语句去掉了。
    呵呵。所以我所说的行数要比你的程序中的少1啦。
    老了老了。
      

  4.   

    这么说来,继承类时,再覆盖它的方法,岂非很麻烦,搞不好就会引用子类的变量啊。我对父类执行方法的过程知之甚少,为什么它要执行子类的方法 ,而不执行自己的方法。这不有缺陷吗,这还叫人怎么覆盖。解决办法只能是定义成static?但static变量父类与子类可以共享?
      

  5.   

    楼主不妨看看manning 的Swing-2d
    里面有这样几句话(P591):As we discussed, the getRowCount() and getColumnCount() methods should return the
    number of rows and columns, respectively. So their implementation is fairly obvious. The
    only catch is that they may be called by the AbstractTableModel constructor before any
    member variable is initialized. So we have to check for a null instance of m_vector. Note that m_columns, as a static variable, will be initialized before any nonstatic 
    code is executed (so we don’t have to check m_columns against null).
      

  6.   

    这个问题是谁先被运行的问题,如果类中一个属性是static的,那么它就会在第一个对象实例化之前被初始化,而非static的属性就会在对象实例化时被初始化。所以才会出现空指针。我们不建议使用DefaultTableModel的一个原因也就在此。我们在这里可以使用AbstractTableModel类。这个类不存在默认的构造方法。事实上,它也只需要定义如你类中所提供的少数几个方法就可以完成TableModel的定义了。对于覆盖的问题,我觉得应该慎重,需要了解父类的调用关系。