使用循环创建 JFormattedTextField 时出现 ArrayIndexOutOfBoundsException
ArrayIndexOutOfBoundsException when using loop for creating JFormattedTextField
我想创建几个JFormattedTextFields
,但总是得到ArrayIndexOutOfBoundsException
,我不明白为什么。
变量 globalZaehler2
是 51 然后我会得到异常。但是我的循环说它必须是 < field.length
(即 51)。那么globalZaehler2
不可以是51吗?当我使用 ((JFormattedTextField)field[globalZaehler2]).selectAll();
时,Eclipse 显示异常
for (globalZaehler2 = 0; globalZaehler2 < field.length; globalZaehler2++) {
if (field[globalZaehler2] instanceof JFormattedTextField) {
((JFormattedTextField)field[globalZaehler2]).addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
((JFormattedTextField)field[globalZaehler2]).selectAll();
// do something with the text in the field
}
});
}
}
我们不太容易分辨,但名称 globalZaehler2
听起来像是一个字段,而不是局部变量。在 for
循环中为 "index" 变量使用字段几乎 总是 一个坏主意......我不记得上次我想要状态在循环中像这样更改的对象。
这意味着在 actionPerformed
执行时,您可能已经多次执行循环,使用不同长度的字段。但是,如果您尝试使它成为一个局部变量,您会遇到一个不同的问题,因为您在匿名内部 class 中引用它 - 这意味着它需要是一个 final 局部变量...这就是真正的问题所在。
基本上,您希望 actionPerformed
中的代码使用 globalZaehler2
的值进行循环迭代 ... 但它没有执行在循环的那个迭代期间...它在动作侦听器触发时执行。
您可以通过在循环中声明一个局部变量来解决这个问题:
for (globalZaehler2 = 0; globalZaehler2 < field.length; globalZaehler2++) {
// In Java 8 you wouldn't need the final part
final int copy = globalZaehler2;
// Use copy instead of globalZaehler2 within actionPerformed
}
但是,更好的解决方案有两个方面:
- 当您 仅 使用
for
循环中的变量作为数组的索引,并且遍历整个数组时,请使用增强的for 循环
- 如果您发现自己在代码中多次使用同一个子表达式,请将其提取为单个表达式
在你的情况下,这将是:
// We don't know the type of field, so it's hard to guess the
// type here. Likewise I *would* use the name field, but that's the
// name of the array... it should probably be called fields, as it's
// naturally plural...
for (Object fooField : field) {
if (fooField instanceof JFormattedTextField) {
// Again, don't bother with final in Java 8
final JFormattedTextField textField = (JFormattedTextField) fooField;
textField.addActionListener(new ActionListener()) {
@Override public void actionPerformed(ActionEvent e) {
textField.selectAll();
// etc
}
});
}
}
现在你自然地在循环中得到了一个新的局部变量(textField
)所以它可以有效地final
,并且在 actionPerformed
方法中使用。
我想创建几个JFormattedTextFields
,但总是得到ArrayIndexOutOfBoundsException
,我不明白为什么。
变量 globalZaehler2
是 51 然后我会得到异常。但是我的循环说它必须是 < field.length
(即 51)。那么globalZaehler2
不可以是51吗?当我使用 ((JFormattedTextField)field[globalZaehler2]).selectAll();
for (globalZaehler2 = 0; globalZaehler2 < field.length; globalZaehler2++) {
if (field[globalZaehler2] instanceof JFormattedTextField) {
((JFormattedTextField)field[globalZaehler2]).addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
((JFormattedTextField)field[globalZaehler2]).selectAll();
// do something with the text in the field
}
});
}
}
我们不太容易分辨,但名称 globalZaehler2
听起来像是一个字段,而不是局部变量。在 for
循环中为 "index" 变量使用字段几乎 总是 一个坏主意......我不记得上次我想要状态在循环中像这样更改的对象。
这意味着在 actionPerformed
执行时,您可能已经多次执行循环,使用不同长度的字段。但是,如果您尝试使它成为一个局部变量,您会遇到一个不同的问题,因为您在匿名内部 class 中引用它 - 这意味着它需要是一个 final 局部变量...这就是真正的问题所在。
基本上,您希望 actionPerformed
中的代码使用 globalZaehler2
的值进行循环迭代 ... 但它没有执行在循环的那个迭代期间...它在动作侦听器触发时执行。
您可以通过在循环中声明一个局部变量来解决这个问题:
for (globalZaehler2 = 0; globalZaehler2 < field.length; globalZaehler2++) {
// In Java 8 you wouldn't need the final part
final int copy = globalZaehler2;
// Use copy instead of globalZaehler2 within actionPerformed
}
但是,更好的解决方案有两个方面:
- 当您 仅 使用
for
循环中的变量作为数组的索引,并且遍历整个数组时,请使用增强的for 循环 - 如果您发现自己在代码中多次使用同一个子表达式,请将其提取为单个表达式
在你的情况下,这将是:
// We don't know the type of field, so it's hard to guess the
// type here. Likewise I *would* use the name field, but that's the
// name of the array... it should probably be called fields, as it's
// naturally plural...
for (Object fooField : field) {
if (fooField instanceof JFormattedTextField) {
// Again, don't bother with final in Java 8
final JFormattedTextField textField = (JFormattedTextField) fooField;
textField.addActionListener(new ActionListener()) {
@Override public void actionPerformed(ActionEvent e) {
textField.selectAll();
// etc
}
});
}
}
现在你自然地在循环中得到了一个新的局部变量(textField
)所以它可以有效地final
,并且在 actionPerformed
方法中使用。