【问题标题】:NPE with initialized variable [duplicate]具有初始化变量的 NPE [重复]
【发布时间】:2019-01-24 04:29:48
【问题描述】:

有人可以向我解释为什么我在 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)

【问题讨论】:

  • 你能添加NullPointerException的堆栈跟踪吗?
  • 如果您的计划是用您自己的方法替换 DefaultTableModel 所做的一切,并使用您自己的列表而不是 DefaultTableModel 使用的数据,请实现 AbstractTableModel 而不是扩展 DefaultTableModel。
  • 不相关:考虑不要在代码中混合语言。而且因为 BeschriftungsMengeBohne 听起来很糟糕,例如,我宁愿全英文InscriptionSetBean
  • 我肯定会接受@JBNizet 的建议并扩展 AbstractTableModel
  • @GuntramBlohm 知道德语中存在的所有特殊术语已经足够复杂了......更不用说找到正确的翻译了......我们的项目绝对没有任何好处,因为说德语是要求

标签: java swing


【解决方案1】:

DefaultTableModel 的构造函数在子类有机会初始化其内容之前调用getRowCount,从而导致 NPE 与您的实现。这是一个糟糕的基类设计,因为从构造函数中调用可覆盖的方法被认为是一种糟糕的做法,但是,嘿,Swing API 有很多这样的:)

参照。 What's wrong with overridable method calls in constructors?

【讨论】:

  • "...因为从构造函数中调用可覆盖的方法被认为是一种不好的做法..." 正是出于这个原因。 :-)
【解决方案2】:

不要扩展DefaultTableModel,而是扩展AbstractTableModel

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

AbstractTableModel 易于扩展(DefaultTableModel 也可以),只需实现这 3 个方法(已在问题代码中完成):

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

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

另一种方法是实现TableModel,但AbstractTableModel 负责一些标准(讨厌?)功能,比如维护监听器。

不好的替代方案,只需检查 null,但这可能会与 DefaultTableModel 代码混淆 - 不要这样做)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-10
    • 1970-01-01
    • 1970-01-01
    • 2016-12-12
    • 1970-01-01
    • 2017-08-13
    • 2013-02-22
    相关资源
    最近更新 更多