Java:在封闭范围内定义的局部variablesmi必须是最终的或有效的最终的

我得到的错误,如主题,我恳请问你如何修复它…错误是在menuItem循环,我尝试设置textArea前景颜色从menuItemselect一个:(颜色[米])

String[] colors = { "blue", "yellow", "orange", "red", "white", "black", "green", }; JMenu mnForeground = new JMenu("Foreground"); for (int mi=0; mi<colors.length; mi++){ String pos = Character.toUpperCase(colors[mi].charAt(0)) + colors[mi].substring(1); JMenuItem Jmi =new JMenuItem(pos); Jmi.setIcon(new IconA(colors[mi])); Jmi.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JMenuItem item = (JMenuItem) e.getSource(); IconA icon = (IconA) item.getIcon(); Color kolorIkony = getColour(colors[mi]); // ERROR HERE: (colors[mi]) textArea.setForeground(kolorIkony); } }); mnForeground.add(Jmi); } public Color getColour(String colour){ try { kolor = Color.decode(colour); } catch (Exception e) { kolor = null; } try { final Field f = Color.class.getField(colour); kolor = (Color) f.get(null); } catch (Exception ce) { kolor = Color.black; } return kolor; } 

这个错误意味着你不能在内部类中使用局部variablesmi


要在内部类中使用variables,必须声明它是final 。 只要mi是循环的计数器,并且不能分配finalvariables,则必须创build一个解决方法来获取可以在内部类中访问的finalvariables中的mi值:

 final Integer innerMi = new Integer(mi); 

所以你的代码将是这样的:

 for (int mi=0; mi<colors.length; mi++){ String pos = Character.toUpperCase(colors[mi].charAt(0)) + colors[mi].substring(1); JMenuItem Jmi =new JMenuItem(pos); Jmi.setIcon(new IconA(colors[mi])); // workaround: final Integer innerMi = new Integer(mi); Jmi.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JMenuItem item = (JMenuItem) e.getSource(); IconA icon = (IconA) item.getIcon(); // HERE YOU USE THE FINAL innerMi variable and no errors!!! Color kolorIkony = getColour(colors[innerMi]); textArea.setForeground(kolorIkony); } }); mnForeground.add(Jmi); } } 

你在这里有一个非局部variableshttps://en.wikipedia.org/wiki/Non-local_variable ),即你访问一个匿名类的方法的局部variables。

方法的局部variables保存在堆栈中,并在方法结束后立即丢失,但是即使在方法结束之后,本地内部类对象仍然在堆中,并且需要访问这个variables(这里,当一个动作被执行)。

我会build议两个解决方法:要么你让你自己的类,实现actionlistenner ,并作为构造函数参数,你的variables,并保持它作为一个类的属性。 因此你只能在同一个对象中访问这个variables。

或者(这也许是最好的解决scheme)只是限定variablesfinal的副本,以便在内部作用域中访问它,因为错误使其成为一个常量:

这将适合你的情况,因为你没有修改variables的值。

是的,这是因为你正在访问匿名内部类中的mivariables,深层内部发生的是variables的另一个副本被创build并将在匿名内部类中使用,所以为了保证数据的一致性,编译器会尝试限制你从改变mi的价值,这就是为什么它告诉你把它设置为最终。