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"))
Related
Non-static final variables can be assigned a value only once.
But why this assignment can happen only either within a declaration or in the constructor?
A final variable is defined to be immutable i.e., the value assigned to it will be the one and only for that variable x. As one can read from the JLS(§4.12.4.)
A variable can be declared final. A final variable may only be
assigned to once.
Now the constructor is just like any other method, except that it is the one that gets executed first when an object (non-static) is created from the class.
Hence, final variables can be assigned through constructors.
For example take the following code:
public class Test {
public final int x;
public Test(int x) {
this.x = x;
}
}
Compiler accepts this invocation because it is guaranteed that for that particular object its class's constructor gets invoked first and doesn't invoked again (i.e. constructor gets invoked one and only one time during the entire lifetime of object.)
However following code throws error: Non-static field 'x' cannot be referenced from a static context
public class Test {
public final int x;
static {
x = 5;
}
public Test(int x) {
this.x = x;
}
}
Since x is not a static field, it cannot be initiated within a static block.
This code would also throw error: Cannot assign a value to final variable 'x'
public class Test {
public final int x;
public Test(int x) {
this.x = x;
}
public void setX(int x) {
this.x = x;
}
}
That is because it is not guaranteed for this object, that the method setX would run first and only once. The programmer could call this method multiple times. Hence, the compiler throws an error.
So there is no way to make a variable "initializable" only once (e.g.,
a setter would block if variable was already assigned before) solely
with java syntax? I thought final might work this way but now I see
it's not.
For your question, you could simply make a variable private and add the condition to the setter method to add value only if variable is null.
For example:
public class Test {
private Integer x;
public Test() {
}
public Test(int x) {
this.x = x;
}
public void setX(int x) {
if (null == this.x) this.x = x;
}
public static void main(String[] args) {
Test y = new Test(5);
System.out.println(y.x);
y.setX(20);
System.out.println(y.x);
}
}
This is not thread safe by the way. I just added a simple example.
What does the keyword final mean in Java?
When used in a class declaration, it means that the class cannot be extended.
When used in a method, it means that the method cannot be overridden.
When used in a method parameter, it means the value of such parameter cannot be changed inside the method. (local constant)
When used in a class field ("variable), it means that it is a global constant.
Values for constants must be resolved at compile time. And, as the word implies, constants fields cannot change value. Therefore, the compiler does not allow the value to be set from a setter (mutator) method.
Contrary to what many believe, for a field to be constant, it does not have to be declared static and final. That said, since the value of a constant cannot be changed, each class instance will share the same value. Therefore, explicitly making them static reenforces this notion.
There is a fifth use of the keyword final and this is when used when local variables are declared. This is a more lengthy explanation.
What happens when you compile code?
I updated my answer because I think part of the problem is that some developers don't quite understand what happens when the code is compiled. As I mentioned before, constant values are resolved at COMPILE TIME. To understand this concept, consider the following example:
public class MyClass {
private final double PI = 3.14159;
// rest of class left out intentionally
}
If I compile this class on my laptop and then I deploy the code to some remote server, how does the server know that the global constant field PI has an assigned value of 3.14159? This is because when I compile this code, this value gets packaged with the byte code. The class constructor doesn't come into play at all in this case. HOWEVER, if the constant field is initialized to its DEFAULT value, then permanent (constant) value may be assigned via the constructor
public class MyClass {
private final double PI; // default value of 0.0
public MyClass(double value) {
PI = value;
}
// rest of code omitted intentionally
}
Here's where declaring a constant as static makes a difference. If a constant is also static, you can't do the above because calling a constructor implies that you can have multiple instances of MyClass and each instance could set a different value. This is clearly a violation of what a static member is. So, if you MUST declare a field as both static and final, understand that you cannot assign a value using this second approach. Only the first one I showed is allowed.
Final Stop's a Variable’s Reassignment
a short simple answer:
Use the keyword final when you want the compiler to prevent a variable from being re-assigned to a different object.
Whether the variable is a static variable, member variable, local variable, or argument/parameter variable, the effect is entirely the same.
Hope this helps friend =)
#StaySafe
Was going through a closure example for the first time , but I'm having a hard time wrapping my head around the control flow.
public class TestLambdaClosure {
public static void main(String[] args) {
int a= 10;
int b=20;
//doProcess(a, i-> System.out.println(i+b));
doProcess(a, new Process() {
#Override
public void process(int i) {
System.out.println(i+b);
}
});
}
public static void doProcess(int i, Process p) {
p.process(i);
}
interface Process{
void process(int i);
}
}
How does 'b' get in the scope when p.process(i) is called? Also, how does the control flow work here internally?
Closures allow you to model behavior by encapsulating both code and context into a single construct.
The key concept is that your function code (lambda) can refer to not only its own variables, but also to everything outside visible for the code, variables a and b in your case.
In Java, closures can refer only to final or effectively final variables. It means, the reference of the variable cannot change and the closure sees only the actual immutable state (the value is actually not immutable, final means the variable cannot be reassigned). In the theory, this is not necessary. For example in JavaScript, you can write such code:
function newCounter() {
let count = 0;
return function() { return ++count; };
}
const nc = newCounter();
console.log(nc()); // 1
console.log(nc()); // 2
console.log(nc()); // 3
Here, the inner function of newCounter still has access to count (its context) and can modify it (the variable is mutable).
Notice, that variable counter is not accessible to any other parts of your code outside of the closure.
Closures let you access variables in their outer scopes. Outer scope variable in this case (b) is declared as what java community now it calls effectively final, meaning that it's value isn't changed since initialization ( int b = 20 ) in order to be accessible.
Bare in mind that variables need to be declared as final or effectively final in order for this to work as closures.
Now regarding your code, this code declares doProcess(...) method that returns a method for partial performing of the doProcess(...) method.
The process(...) method accesses b in the outer scope of the doProcess(...) method, which is declared as effectively final.
new to the community, and new to the whole programming world.
While I was studying java, I stumbled on a simple question.
In a main method (or any method), I can declare and initialize a primitive variable on different line just fine. Say,
public static void main (Strin[]args){
int age;
age = 42;
}
will complile just fine.
But if I tried this outside a method, as a class variable or instance variable,
public class test {
int age;
age = 42;
}
the code won't compile. It will only work if the variable is declared and initialized in one line. I was wondering why java doesn't allow this outside a method.
A class body can contain variable declarations and method declarations, but no single statements. When would you expect such a statement to be executed? So your initialization has to be either inline with the declaration (as a shortcut) or in some method, e.g. in the constructor, if you want to initialize the variable when creating a new object.
It is a syntax error! Your code does not comply with the Java syntactic and semantics rules as described in Java Language Specification.
You have to initialise it's value inside the constructor (that's the whole point of a constructor), like
public test() {
age = 42;
}
For static variables it's possible to give them a value:
static int age = 42;
Or use a static block:
static {
age = 43;
}
I need to know how to call a variable from one method to another
Can anyone help me?
public static void number(){
number = 1;
}
public static void callNumber(){
/*How can I call number to this method???
*/
}
Actually, "call a variable from an other method" is not very explicit, since a variable in a method is either global (used in the method but naturally available in the entire program), or a local variable of the method.
And in this last situation it is impossible to get this value.
Then either you declare your variable externally and it is trivial, or you specifiy a type value to your method "number()":
public static int number() {
int number = ...;
return number;
}
and you call it:
public static void callNumber() {
int numberReturned = number();
// other things...
}
Note: your code number = 1; specifies that your variable is global...
The trick is to set "number" available either by the return of the method, or by specifying this variable global.
I don't know if I've answered your question, if not try to be more explicit.
Between static methods, variables can be shared by making them global,
or by sending them as parameters(noas described by #Gaétan Séchaud).
However, if those two methods has a continuos connection between them, and they handle some variables needed to be shared, it smells like a class is needed.
private final List<KeyListener> keyListeners= new CopyOnWriteArrayList<KeyListener>();
public void addKeyListener(KeyListener keyListener){
keyListeners.add(keyListener);
}
In the above code I declare keyListeners to be final and also it is thread-safe . I assume by final I mean that the state of the listener can not change after construction . But am I not doing the same in the addKeyListener() method ? Why does the compiler doesn't give me an warning ? What am I missing here ?
Adding the final keyword means that keyListeners will point to the same CopyOnWriteArrayList throughout the entire program. It would be illegal to do:
keyListeners = null
However, methods of keyListeners can still be called freely. Whether they affect the underlying data structure is not something the compiler cares about.
class Foo {
public int bar = 1;
public static void test() {
final Foo x = new Foo();
//This is perfectly legal:
x.bar = 2;
//This is not:
x = new Foo();
}
}
Final keyword is used to tell that the variable may only be assigned to once. But you can call method on it even if it "change" object properties.
From the JLS :
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.
Just because final refere to internal address of keyListeners and not to th List itself.