getAccessibleChild() 方法的 JTable 奇怪行为导致客户端代码中出现空指针
我遇到了 JTable (JDK 1.5_22) 的奇怪行为:
在表中进行选择更改后以及在某些未知的特定情况下,JTable 将使用值参数“null”来调用单元格渲染器。
这最终将导致自定义渲染器代码上出现一个很好的“空指针异常”,而该代码尚未准备好进行此类粗鲁的调用。
这是有罪的方法(JTable.java,第 5319 行):
public Accessible getAccessibleChild(int i) {
if (i < 0 || i >= getAccessibleChildrenCount()) {
return null;
} else {
// children increase across, and then down, for tables
// (arbitrary decision)
int column = getAccessibleColumnAtIndex(i);
int row = getAccessibleRowAtIndex(i);
TableColumn aColumn = getColumnModel().getColumn(column);
TableCellRenderer renderer = aColumn.getCellRenderer();
if (renderer == null) {
Class<?> columnClass = getColumnClass(column);
renderer = getDefaultRenderer(columnClass);
}
Component component = renderer.getTableCellRendererComponent(
JTable.this, null, false, false,
row, column);
return new AccessibleJTableCell(JTable.this, row, column,
getAccessibleIndexAt(row, column));
}
}
这里重点关注错误的语句:
Component component = renderer.getTableCellRendererComponent(
JTable.this, null, false, false,
row, column);
询问 googlewhith“JTable getAccessibleChild 5334”很有趣:我并不是唯一一个遇到这个“功能”的人。但没有得到任何答复。
最完善的问题位于官方 Sun 论坛。
有人对此有线索吗?
I've encountered a strange behavior from JTable (JDK 1.5_22):
After a selection change in the table and under some unknown particular circumstances, the JTable will call the cell renderer with 'null' for the value parameter.
This will eventually lead to a nice 'Null Pointer Exception' on a custom renderer code that is not ready for such a rude call.
Here is the guilty method (JTable.java, line 5319) :
public Accessible getAccessibleChild(int i) {
if (i < 0 || i >= getAccessibleChildrenCount()) {
return null;
} else {
// children increase across, and then down, for tables
// (arbitrary decision)
int column = getAccessibleColumnAtIndex(i);
int row = getAccessibleRowAtIndex(i);
TableColumn aColumn = getColumnModel().getColumn(column);
TableCellRenderer renderer = aColumn.getCellRenderer();
if (renderer == null) {
Class<?> columnClass = getColumnClass(column);
renderer = getDefaultRenderer(columnClass);
}
Component component = renderer.getTableCellRendererComponent(
JTable.this, null, false, false,
row, column);
return new AccessibleJTableCell(JTable.this, row, column,
getAccessibleIndexAt(row, column));
}
}
and here is a focus on the faulty statement:
Component component = renderer.getTableCellRendererComponent(
JTable.this, null, false, false,
row, column);
Asking google whith "JTable getAccessibleChild 5334" was interesting: I'm not alone to encounter this 'feature'. But there were no answer.
Most well formulated question is located on official sun forum.
Does anyone have a clue about this ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这不是同步或 EDT 问题。
JTable
中的代码使用 null 值显式调用getTableCellRendererComponent
。返回的值从未被使用过,因此,从表面上看,它看起来很像旧的调试代码。但是我怀疑它不会破坏期望在访问单元格之前调用 getTableCellRendererComponent 的代码。
Sun 之前曾就这个问题进行过咨询,他们的答案是 API 不保证
value
不为 null,因此当使用 null 调用时,getTableCellRendererComponent
必须正常失败。It's not a synchronization or EDT issue. The code in
JTable
is explicitly callinggetTableCellRendererComponent
with a null value.The value returned is never used, so, on the surface, it rather looks like old debugging code. However I suspect it is there to not break code that expects
getTableCellRendererComponent
to be called before a cell is accessed.Sun has been called on this issue before and their answer was that the API makes no guarantees that
value
is non-null, sogetTableCellRendererComponent
must fail gracefully when called with a null.每当我看到像这样无法解释的问题时,我都会想知道同步是否不正确。例如,
1) 未能在 事件调度上构造组件线程。
2) 在其他线程上改变组件的模型。
在存在复杂初始化、具有意外延迟的模型或不同硬件的情况下,违规行为会更频繁地出现。也可能存在错误,但是这两点值得检查。
Anytime I see otherwise inexplicable problems like this, I wonder about incorrect synchronization. For example,
1) Failing to construct the component on the event dispatch thread.
2) Mutating the component's model on some other thread.
Violations manifest more frequently in the presence of complex initialization, a model with unexpected latency, or different hardware. There may also be a bug, but these two points are worth checking.