我已经实现了一个自定义表模型如下:
public class MyTableModel extends AbstractTableModel {
...
...
@Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
...
...
}
当我显示具有上述TableModel的JTable时,我得到上述方法抛出的NullPointerException。
我认为异常是由于数据库表中的一些空单元格所致。
如果异常是由数据库表中的空单元格引起的,那么如何解决这个问题?
数据库中的每个列都不一定具有某些值。有些列可以不包含任何内容。
答案 0 :(得分:1)
一个问题是为什么要为这些特定坐标获取null。 如果它是合法的并且你只是想要渲染没什么特别的,那么你需要做的是null-check并返回Object.class,例如:
public Class getColumnClass(int c) {
Object o = getValueAt(0, c);
if(o==null) return Object.class;
return o.getClass()
}
这将确保使用默认渲染器,并且由于没有值,因此不会渲染任何内容。
答案 1 :(得分:1)
如果单元格可以包含空值,那么在空值上调用getClass()肯定会给你NPE。当然你可以检查null,但你真正的问题比那更微妙。
TableModel接口指定getColumnClass(int)应返回“列中所有单元格值的最特定超类。”从外观上看,您可以返回任意数量的单个列的类类型,有效地破坏了TableModel契约。
通常,列类型对于给定的一组表数据是静态的,这意味着除非基础表数据已更改,否则列的类不应更改。我认为重要的是要问你为什么需要返回这样一个特定值。
如果您想要为给定的类类型呈现特定的内容,最好滚动自己的TableCellRenderer,并在每个单元格的基础上确定对象类型。从那里你可以根据需要进行任何特定的渲染。
答案 2 :(得分:0)
也许:
public Class getColumnClass(int c) {
return (getValueAt(0, c) == null ? Object.class : getValue(0, c).getClass());
}
我希望它可以帮到你。
答案 3 :(得分:0)
除了目前为止的答案:假设您的模型由List
支持(如上一个问题所示),如果您尝试渲染IndexOutOfBoundsException
,则会看到JTable
当TableModel
不包含任何行时(即List
为空)。这是一个讨厌的边缘情况(因为我意识到你试图渲染ResultSet
- 你怎么知道ResultSet
不会是空的?)。
为了避免这种情况,你为什么不按照我最初的建议行事并从ResultSetMetaData
确定每个栏目的班级?
答案 4 :(得分:0)
ResultSetMetaData不提供有关该类的任何信息。它确实提供了特定于数据库的数据类型,它们不会自动映射到Java类(例如,PostgreSQL世界中的“cidr”或“int8”)所以这个建议(顺便提一下,它不包含任何源代码)实际上并没有帮助。
另外,Jason Nichols的评论“我认为重要的是要问你为什么需要返回这样一个特定的值”,这表明对于如何在现实世界中使用JTable类一直毫无头绪。
我想找到一个解决这个问题的方法,其中表有零行,我仍然可以找到我应该用来为整个列渲染单元格的Java类。输出可以改变的想法是基于对数据库的更多无知 - 列数据类型在该列的定义中指定,无论其内容是什么,数据类型都不会根据您的哪一行而改变看它。
当然,数据库面临的挑战之一是列定义可能允许也可能不允许NULL值,任何对JTable进行子类化的人都应该理解这个非常基本的前提并知道如何测试它。