Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Local variable mi defined in an enclosing scope must be final or effectively final

Tags:

java

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; } 
like image 487
mallorn Avatar asked Nov 19 '15 09:11

mallorn


People also ask

What is enclosing scope in Java?

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.

How do you declare a variable as effectively final?

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.

Why local variables referenced from a lambda expression must be final or effectively final?

Forcing the variable to be final avoids giving the impression that incrementing start inside the lambda could actually modify the start method parameter.


2 Answers

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);     } } 
like image 67
Jordi Castilla Avatar answered Sep 21 '22 09:09

Jordi Castilla


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.

like image 42
QuakeCore Avatar answered Sep 21 '22 09:09

QuakeCore