I am not understanding the concept of final variable. In a for loop I have dynamic variable i which is crucial for me to refer an array. As soon as I use i, it throws me an error saying it should be final.
What exactly is final? Could you please help to get rid of that error?
My code is here:
for( int i = 0; i <4; i++)
{
Bitmap celeb1=Bitmap.getBitmapResource(fimagearray[i]);
Bitmap celeb1_focus=Bitmap.getBitmapResource(fimagearray[i]);
ImageButton celebbutton = new ImageButton(celeb1, celeb1_focus);
celebbutton.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context)
{
UiApplication.getUiApplication().pushScreen(new FetchTweets(fusernamearray[i]));
}
});
femaleSec.add(celebbutton);
}
An anonymous inner class can only access final variables from the outer scope. Since i is not final, it can't be accessed directly. You can't make i final since it needs to change, and a final variable can't be changed.
As a simple workaround, copy the value of i into a final variable during each loop iteration:
for( int i = 0; i < 4; i++)
{
final int index = i; // <-- copy i to `index' to use in FieldChangeListener
// ...
celebbutton.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context)
{
UiApplication.getUiApplication().pushScreen(
new FetchTweets(fusernamearray[index])); // <-- `index'
}
});
femaleSec.add(celebbutton);
}
A final variable can only be initialized once, either via an initializer or an assignment statement
Check out the this link for it.
Also Look at this Example.
You are attempting to use the value of i inside of an 'Anonymous Inner Class' which requires that all non-local variables to that class be declared as final, meaning that the variable's value may not be changed once it has been initialized.
The solution posted by #aix would solve your problem.
Related
I have an array of seats, and the array has two strings(selected and empty). On mouse click, I want to traverse the array and find the selected seat. When I press the button it says:
The final local variable seatno cannot be assigned, since it is defined in an enclosing type.
JButton btnContinue = new JButton("Next");
btnContinue.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent arg0) {
for(int x=0;x<17;x++){
if(anArray[x]=="selected"){
seatno = anArray[x];
}
}
data page=new data(newfrom,newto,newtime,date2,seatno);
page.setVisible(true);
setVisible(false);
}
});
btnContinue.setBounds(358, 227, 62, 23);
contentPane.add(btnContinue);
The point is that method-local variables from the enclosing type are actually copied to instances of anonymous classes (this is because of activation frame issues, but I won't go further into detail as this is not really relevant to the question), which is why they need to be final, because the variable in the nested type instance is not the same anymore.
So, here is the first example:
void foo() {
int a = 3;
new Runnable() {
#Override
public void run() {
a += 3;
}
};
}
This does not compile, because you cannot reference a non-final variable in an anonymous class' method. When you add a final modifier to the declaration of a, the value of a would be copied into the created instance of the anonymous class you have defined. However, you will not be allowed to change the value of a, because the changes would not be visible to the method where a was declared.
However, anonymous classes are not static, that is, they have a reference to the enclosing instance (unless the method where they are declared is static) which you can use to modify variables of the enclosing instance:
int a = 3;
void foo() {
new Runnable() {
#Override
public void run() {
a += 3;
}
};
}
This example does compile and it would increase a by 3 every time the run() method of the anonymous class' instance is called. (In this example it is never called, but it is just an example.)
So, to summarize, you need to convert the variable seatno from a method-local variable to an instance variable of the enclosing type. Or, if it is yet, you need to remove the final modifier as final variables can only be assigned once.
Update: In Java 8, the concept of effectively final variables is introduced (see Java Language Specification). However, in the first example of this post, the variable a is assigned multiple times, which prevents it from being effectively final. This means that this example still does not compile with Java 8. (The compile error is "Local variable a defined in an enclosing scope must be final or effectively final")
A final variable cannot change it's value (it's similar to const from C/C++).
You probably want to make it a field in a class (without the final keyword of course), not a local variable inside a function.
Instead of defining a class member variable you can also use a mutable int to achieve the same.
void foo() {
final MutableInt a = new MutableInt(3);
new Runnable() {
#Override
public void run() {
a.add(3);
}
};
}
Since MutableInt is not primitive type (hence passed by reference) and can be reassigned this works.
I recently faced similar problem. In my case it was easier to create final array (or collection) and to add variable, that I wanted to change inside anonymous class, to this array, as below.
int a = 3;
final int[] array = new int[1];
array[0] = a;
new Runnable() {
#Override
public void run() {
array[0] += 3;
}
};
Without knowing the declaration of seatno, I'd suggest to introduce a new variable in the mouseClicked() method that is not final and does the same job as seatno currently does, as the variable seems only to be used inside that method.
By the way: Capitalize your class names (data should be Data). Will look much more clear.
Make sure your variable doesn't have the final modifier.
//final, can be set only when the object is created.
private final String seatno;
//no final modifier, the value can be set every time you "want"
private String seatno;
Also, to compare Strings you should use equals:
if(anArray[x].equals("selected"))
JLS 8.1.3 gives us the rule about variables which are not declared in an inner class but used in the class.
Any local variable, formal parameter, or exception parameter used but
not declared in an inner class must either be declared final or be
effectively final (§4.12.4), or a compile-time error occurs where the
use is attempted.
An example:
class A{
void baz(){
int i = 0;
class Bar{ int j = i; }
}
public static void main(String[] args){
}
}
DEMO
Why was the code compiled? We used the non-final local variable in the inner class which was no declared in there.
Variable i defined inside method baz is effictively final because value of variable i is not modified elsewhere. If you change it
void baz(){
int i = 0;
i = 2;
class Bar{ int j = i; }
}
The code will fail to compile because variable i is no longer effictively final but if you just declare the variable i and the initialize it in another line, the code will compile because the variable is effictively final
void baz(){
int i;
i = 2;
class Bar{ int j = i; }
}
i is effectively final, since it is never modified. As you yourself quoted the JLS, the inner class may use effectively final variables.
Because i is effectively final as it is not changed in baz.
The following code won't compile because the compiler isn't gauranteed that the data field f would be initialized. How do you fix this?
import java.util.Scanner;
public class Foo
{
private final int f;
/*constructor*/
public Foo()
{
Scanner sc = new Scanner(System.in);
for(int i = 0; i < 10; i++)
{
if(i == 5)
f = sc.nextInt();//error: variable f might be assigned in a loop
}
}
public Foo(int i)
{
j = i;//no problem
}
}
Isn't this kind of a glitch in the language because in my other constructor I can have f set to final and just because it's not done in a loop it works. I know the compiler (being dumb) sees a loop and thinks f will be reassigned, but the logic in the program ensures it only happens once. Is this an example of how Java "protects" the programer?
For everyone wondering why f was declared as final Netbeans suggested it, presumably when the code was much different.
private final int f;
↑
Remove the final keyword. The compilers doesn't know that the if will be satisfied only once and you'll get an error about trying to change f multiple times:
The final field f may already have been assigned
First of all, final field is field that you can not change value that is assigned to. In your case in each loop move you change that value, so it can not be compile. Remove final word before f.
public class Foo
{
private int f;
/*constructor*/
public Foo()
{
Scanner sc = new Scanner(System.in);
for(int i = 0; i < 10; i++)
{
if(i == 5)
f = sc.nextInt();
}
}
}
You .. don't.
I know the compiler (being dumb) sees a loop and thinks f will be reassigned, but the logic in the program ensures it only happens once. Is this an example of how Java "protects" the programmer?
This behavior, whether or not it "protects" the programmer, is a result of how the Java language is defined (per the JLS) and how the compiler correctly enforces the language specification.
4.12.4. final Variables:
A final variable may only be assigned to once .. It is a compile-time error if a final variable is assigned to unless it is definitely unassigned (§16) immediately prior to the assignment.
See Chapter 16. Definite Assignment which discusses the rules for this limited static analysis case in detail.
private final int f;
You use final for your declaration this will not allow to re-assign another value for f
A final variable can only be initialized once, either via an
initializer or an assignment statement.
Read more about final here
so just use
private int f;
When u declare any variable as final, the value of that value should not be changed.By the way is there any need to declare your variable as final?
Here is the catch, you can initialize any final instance on the same place or inside the constructor, but can not initialize inside method( METHOD ).
So you will say that I am initializing inside the constructor!! But the thing is that you are changing final instance variable's value multiple time inside for loop which compiler identifies and throws compiler error.
compiler inline final code like below.
private final int f = 10 //even if you initialize it inside the constructor only one time.
ex
public class Foo {
private final int f; // byte code becomes 'private final int f = 10' for each instance
Foo() {
f = 10;
}
}
I have a global variable in a recursive class, each time I call it, the variables are created. The variable at begin is: int count = 0, then in the method I increase: count ++, the problem is when call again the class, the variable is reset to zero. I need the variable "count" remains in 1, to again increase in each call to 2,3,4.... etc
I try with this: private static int count = 0; but not work..
Search the code for all references to your count variable. Most likely, you are re-setting to 0 somehow. For example:
private class MyClass {
private static int count = 0;
public MyClass() {
count = 0; //Bad line
}
public void incrementCount() {
count++;
}
}
If you have something like that, then every time you create a new MyClass object, you would be resetting count to 0 for all MyClass objects.
But you really need to add your class code to your question. Otherwise we can't help.
can anyone tell me why I get this error?
illegal start of expression private int confirm;
and also
illegal start of expression private File soundFile3 = new File("merge.wav");
If I remove the word "private" the compiler doesn't show any errors.
The code is part of a public method.
Why?
Thank you.
the code is:
private int confirm;
confirm = JOptionPane.showConfirmDialog(this,
"Different sample size....",
"JOin", JOptionPane.OK_CANCEL_OPTION);
if (confirm != JOptionPane.OK_OPTION) {
return;
}
private File soundFile3 = new File("merge.wav");
private keyword cannot be used inside methods. it can be used to declare class fields or methods:
class Foo {
private int num; //private can be specified here
public void foo() {
int s = 1;
int k = num+s; //no private here
}
}
I guess you cannot put an access modifies except final in a method. It makes no sense to have a private modifier for a method level variable. As methods variables are created in their separate stack and destroyed when the scope is lost.
You should use access modifiers only on class members, not local variables.
Local variables are always visible only in the scope of the block where they were declared. So, if you declare a variable in your method, that variable will be visible only within that method. So, no need to use private there. I mean, no need even if you could.