I get the error, as in subject, and I kindly ask you how to repair it... ERROR is in menuItem-loop, where I try to set the textArea foreground colour to one picked from menuItem: (colors[mi])
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; }
Since it is a rule in Java programming language that variable in an enclosing scope can't be change in inner class or lambda expression, so you can't change the value of the variable.
An effectively final variable is one whose value doesn't change after it's first assigned. There is no need to explicitly declare such a variable as final, although doing so would not be an error.
Forcing the variable to be final avoids giving the impression that incrementing start inside the lambda could actually modify the start method parameter.
The error means you cannot use the local variable mi
inside an inner class.
To use a variable inside an inner class you must declare it final
. As long as mi
is the counter of the loop and final
variables cannot be assigned, you must create a workaround to get mi
value in a final
variable that can be accessed inside inner class:
final Integer innerMi = new Integer(mi);
So your code will be like this:
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); } }
Yes this is happening because you are accessing mi
variable from within your anonymous inner class, what happens deep inside is that another copy of your variable is created and will be use inside the anonymous inner class, so for data consistency the compiler will try restrict you from changing the value of mi
so that's why its telling you to set it to final.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With