有人可以向我解释为什么我在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)
答案 0 :(得分:28)
DefaultTableModel
的构造方法在子类有机会初始化其内容之前调用getRowCount
,从而导致NPE的产生。这是基类的不良设计,因为从构造函数内部调用可重写方法被认为是不良做法,但是,Swing API有很多这样的方法:)
Cf。 What's wrong with overridable method calls in constructors?
答案 1 :(得分:13)
请勿扩展DefaultTableModel
,而应扩展AbstractTableModel
。
DefaultTableModel
使用Vector来维护数据,并且不希望您在子类中拥有自己的数据。正如@spi所写,它正在调用getRowCount
,该值被重写以返回尚未初始化的data
的大小。
AbstractTableModel
易于扩展(DefaultTableModel
也很容易扩展),只需实现以下3种方法(已在问题代码中完成):
public int getRowCount();
public int getColumnCount();
public Object getValueAt(int row, int column);
可以重写其他方法来调整其行为,例如isCellEditable
或getColumnClass
。如果更改了数据,则应调用适当的fireXXX
方法,以便调用已注册的侦听器(例如,使用该模型的JTable
)。
另一种方法是实现TableModel
,但是AbstractTableModel
会处理某些标准(讨厌的?)功能,例如维护侦听器。
(不好的替代方法,只需检查null
,但这可能会与DefaultTableModel
代码混淆-不要这样做)