13
 private void pushButtonActionPerformed(java.awt.event.ActionEvent evt)
{
    final int c=0;
    final JDialog d=new JDialog();
    JLabel l=new JLabel("Enter the Element :");
    JButton but1=new JButton("OK");
    JButton but2=new JButton("Cancel");
    final JTextField f=new JTextField(10);
    JPanel panel = new JPanel();
    but1.addActionListener(new ActionListener()
    {
        public void actionPerformed(ActionEvent e)
        {
            c=Integer.parseInt(f.getText());
            d.setVisible(false);
            d.dispose( );
        }
     });
but2.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e){
        d.setVisible(false);
        d.dispose( );
    }
});
}

I am using netbeans 7.1.1. This is my code here i have declared 'c' as "final int" but the line "c=Integer.parseInt(f.getText());" i am getting an error "cannot assign a value to a final variable". If i am deleting the word final from the declaration and making it just as "int c" then in the same line i get an error "local variable c cannot be accessed from within a class;needs to be declared final". can anyone tell me why is this happening ?

rick
  • 913
  • 6
  • 13
  • 28

7 Answers7

35

You've got c declared in a function, and then you've created an anonymous inner class within that function. This inner class, the ActionListener, persists past the time your function terminates - so it can't assign values to c, because c is local to the function.

The warning about "final" is misleading - that's just the compiler telling you that you can't access transient local variables from an anonymous class. You can't solve the problem just by making c final, as that would prevent any assignment to it at all, but you can make c an instance member of the class pushButtonActionPerformed is in, instead. Something like this:

class Something
{
    int c;

    private void pushButtonActionPerformed(java.awt.event.ActionEvent evt)
    {
        JButton but1=new JButton("OK");
        but1.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                c=Integer.parseInt(f.getText());
            }
        });
    }
}
banana
  • 603
  • 5
  • 10
  • 1
    The statement that "you can't access transient local variables from an anonymous class" is false. It is also false that a final variable cannot be assigned to. If that were true, there would be no such thing as a final var as it would be useless. What is actually going on is that a **closure** is created that **closes over** the variable in scope of the anonymous class declaration. Java only has the restriction that you can only close over final vars. This is to maintain thread safety. – Marko Topolnik Apr 25 '12 at 15:01
  • Your code example is wrong because you have **not** made a closure, so all instances of the anonymous class will share the same int. – Marko Topolnik Apr 25 '12 at 15:08
  • Aside from Marko's hating above, that was a great explanation and solved my problem. two thumbs up – Ryan Knell Jul 01 '15 at 10:15
14

I'll skip the reasons and cut to the solution: use

final int[] c = {0};
...
c[0] = Integer.parseInt(f.getText());

For the full story refer to this post

Community
  • 1
  • 1
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
6

but the line "c=Integer.parseInt(f.getText());" i am getting an error "cannot assign a value to a final variable

Right. The whole point of final variables is that you can only assign to them once, but you're trying to assign to it twice (once in the initialization setting it to 0, once in your quoted line). From the specification:

A variable can be declared final. A final variable may only be assigned to once. Declaring a variable final can serve as useful documentation that its value will not change and can help avoid programming errors.

It is a compile-time error if a final variable is assigned to unless it is definitely unassigned (§16) immediately prior to the assignment.

A blank final is a final variable whose declaration lacks an initializer.

Once a final variable has been assigned, it always contains the same value. If a final variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object.

(Their emphasis, not mine.)

Instead of trying to track the state you're storing in c in a variable in the method, track it in a data member in the instance of your anonymous ActionListener you're creating.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Make the state you're trying to track in c something you track in your anonymous ActionListener instance rather than in a variable in the surrounding function (I've updated the answer to say that). – T.J. Crowder Apr 16 '12 at 12:45
2

This is the reason that keyword final exists in java. The variable is final, i.e. its value cannot be changed. If you have to change the value do not mark variable as final.

AlexR
  • 114,158
  • 16
  • 130
  • 208
0

a variable is declared with final keyword means its value cannot be changed. final variable are like constants

Chandra Sekhar
  • 18,914
  • 16
  • 84
  • 125
0

final makes the "variable" a constant--you can't change it. As to why the compiler is giving you warnings after you delete the final keyword, we'd need to see the whole code...

EDIT:

 but1.addActionListener(new ActionListener()
 {
     public void actionPerformed(ActionEvent e)
     {
         c=Integer.parseInt(f.getText());
         d.setVisible(false);
         d.dispose( );
     }
  });

I believe this is the segment of code that causes the compiler to fire the warning. You can't use c in this class...

apnorton
  • 2,430
  • 1
  • 19
  • 34
-4

Just remove the final keyword from the declaration and continue your program. As final keyword means the value is unaltered.

Mayur
  • 676
  • 8
  • 16