具有初始化变量的 NPE

2022-09-03 09:10:12

有人可以向我解释为什么我在getRowCount()方法中获得NullPointerException吗?该变量使用空 ArrayList 初始化...

public class BeschriftungssetTableModel extends DefaultTableModel {

    private static final long serialVersionUID = -4980235976337188354L;

    private List<BeschriftungssetBean> data = new ArrayList<>();


    public void setData(List<BeschriftungssetBean> data) {
        this.data = data;
    }

    @Override
    public int getColumnCount() {
        return 1;
    }

    @Override
    public int getRowCount() {
        return data.size();
    }

    @Override
    public Object getValueAt(int row, int column) {
        return data.get(row).getBezeichnung();
    }

    @Override
    public String getColumnName(int column) {
        return "Bezeichnung";
    }

    public static void main(String[] args) {
        BeschriftungssetTableModel beschriftungssetTableModel = new BeschriftungssetTableModel();
        beschriftungssetTableModel.getRowCount();
    }
}



public class BeschriftungssetBean {
    private String objId;
    private String bezeichnung;

    public String getBezeichnung() {
        return bezeichnung;
    }

    public void setBezeichnung(String bezeichnung) {
        this.bezeichnung = bezeichnung;
    }

    public String getObjId() {
        return objId;
    }

    public void setObjId(String objId) {
        this.objId = objId;
    }
}

Exception in thread "main" java.lang.NullPointerException
at ch.aaa.xxx.yyy.gruppen.plugin.anzeige.beschriftungseinstellungen.BeschriftungssetTableModel.getRowCount(BeschriftungssetTableModel.java:36)
at javax.swing.table.DefaultTableModel.setDataVector(DefaultTableModel.java:224)
at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:124)
at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:106)
at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:86)
at ch.aaa.xxx.yyy.gruppen.plugin.anzeige.beschriftungseinstellungen.BeschriftungssetTableModel.<init>(BeschriftungssetTableModel.java:18)
at ch.aaa.xxx.yyy.gruppen.plugin.anzeige.beschriftungseinstellungen.BeschriftungssetTableModel.main(BeschriftungssetTableModel.java:50)

答案 1

子类之前的调用构造函数有机会初始化其内容,从而导致 NPE 与 implem。这是基类的糟糕设计,因为从构造函数内部调用可重写方法被认为是一种不好的做法,但是嘿,Swing API有相当多的这些:)DefaultTableModelgetRowCount

Cf. 构造函数中的可重写方法调用有什么问题?


答案 2

不要扩展 ,而是扩展。DefaultTableModelAbstractTableModel

DefaultTableModel使用 Vector 来维护数据,并且不希望您在子类中拥有自己的数据。正如@spi所写的,它被覆盖以返回尚未初始化的大小的调用。getRowCountdata

很容易扩展(也可以),只需要实现这3种方法(已经在问题代码中完成):AbstractTableModelDefaultTableModel

public int getRowCount();
public int getColumnCount();
public Object getValueAt(int row, int column);

可以重写其他方法以调整其行为,如 或 。如果数据被更改,则应调用适当的方法,以便调用已注册的侦听器(例如 使用该模型)。isCellEditablegetColumnClassfireXXXJTable

另一种方法是实现 ,但要处理一些标准(讨厌的?)功能,如维护侦听器。TableModelAbstractTableModel

糟糕的替代方案,只需检查null,但这可能会弄乱DefaultTableModel代码 - 不要这样做)


推荐