method-local inner class cannot use variables declared within the method - java

Why a method-local inner class can't use variables declared inside the enclosing method except those marked final, i know that the variables declared inside the enclosing method might vanishes while the inner class instance remains valid, but what has changed when this variable/s is declared final?

The reason is that it is specified in the Java Language Specification #8.1.3
Any local variable, formal parameter, or exception parameter used but not declared in an inner class must be declared final.
Also note that project lambda (java 8), which aims at introducing closures in java (to replace anonymous classes), introduces the notion of effectively final which will allow you to use a non final variable within a lambda expression as long as you don't modify it within the closure.

When the variable is final, a copy is placed in the inner class. i.e. it still can't access the variable, but it has a copy it can use.
You can see these copies if you use reflection or with a debugger.

The reason is [ Actually Conclusion from Where are Java final local variables stored? ] : final variables are copied by the compiler into a hidden member variable of the inner class that references it. This way, they are guaranteed to not change after the copy has been made.
Also might be : The Method-Local Inner Class which is on the heap and the variable which is on the stack have different scope. But if the local variable is marked by final, it is stored on the heap.

Now at first i would like to light upon
Does final local variables get stored on a heap instead of stack
?
Explanation: Now after some researching in SO i found out that all local variable (final or not) stored into the stack and go out
of scope when the method execution is over. But about final
variable JVM take these as a constant as they will not change after
initiated . And when a inner class try to access them compiler create
a copy of that variable (not that variable it self) into the heap
and create a synthetic field inside the inner class, so even when
the method execution is over it is accessible because the inner class
has it own copy. Synthetic field are filed which actually doesn't
exist in the source code but compiler create those fields in some
inner classes to make those field accessible. In simple word hidden
field.
So final variable also stored in stack but the copy that variable which a inner class have stored in heap.
So now think about it.The local variables of the method live on the stack and exist only for the lifetime of the method. We already know that the scope of a local variable is limited to the method the variable is declared in. When the method ends, the stack frame is blown away and the variable is history. But even after the method completes, the inner class object created within it might still be alive on the heap if, for example, a reference to it was passed into some other code and then stored in an instance variable. Because the local variables aren't guaranteed to be alive as long as the method local inner class object is, the inner class object can't use them. Unless the local variables are marked final. And it is beneficial making variable final as it can remain like synthetic field.

Final ensures that you won't lose the reference to that variable. You don't want your inner class to destroy or lose your reference since you might continue using it in the context where was declared.

Related

What is the difference between a variable declared in a method and a field declared as a class variable?

Im studying for an exam and im stuck at one question that i cant figure out.
The question is: ''What is the difference between a variable declared in a method and a field declared as a class variable?''
Can someone enlighten me please?
As other people commented this is a basic stuff with variables in a programming language. In java there are types of variables, namely:
Local Variables
Instance Variables
Static Variables.
The variables declared within a method is called a local variable. The life of this variable is inside the method and is not accessible when the method is executed. These variables need to be instantiated when they are declared.
On the other hand, the variables declared outside the method but inside the class are called as Instance variables. These variables become accessible when an object is created for the class. The life of the variables is dependent on the life of the object.
Finally, static variables are same as instance variables but with the "Static" keyword. By the concept of static, they are created when the class is loaded. These can be directly accessed using the classname or the object reference. Only one set of static variables are created for every class. But in case of instance variables, each time you create an object, a set of instance variables are created for that object.
You can find a lot of online resource for this topic, I suggest you refer http://www.geeksforgeeks.org/variables-in-java/.

Java - Class fields (Member Variables) can be used in inner class or lambda expressions but not local variables [duplicate]

In a lambda, local variables need to be final, but instance variables don't. Why so?
The fundamental difference between a field and a local variable is that the local variable is copied when JVM creates a lambda instance. On the other hand, fields can be changed freely, because the changes to them are propagated to the outside class instance as well (their scope is the whole outside class, as Boris pointed out below).
The easiest way of thinking about anonymous classes, closures and labmdas is from the variable scope perspective; imagine a copy constructor added for all local variables you pass to a closure.
In a document of project lambda, State of the Lambda v4, under Section 7. Variable capture, it is mentioned that:
It is our intent to prohibit capture of mutable local variables. The
reason is that idioms like this:
int sum = 0;
list.forEach(e -> { sum += e.size(); });
are fundamentally serial; it is quite difficult to write lambda bodies
like this that do not have race conditions. Unless we are willing to
enforce—preferably at compile time—that such a function cannot escape
its capturing thread, this feature may well cause more trouble than it
solves.
Another thing to note here is, local variables are passed in the constructor of an inner class when you access them inside your inner class, and this won't work with non-final variable because value of non-final variables can be changed after construction.
While in case of an instance variable, the compiler passes a reference of the object and object reference will be used to access instance variables. So, it is not required in case of instance variables.
PS : It is worth mentioning that anonymous classes can access only final local variables (in Java SE 7), while in Java SE 8 you can access effectively final variables also inside lambda as well as inner classes.
In Java 8 in Action book, this situation is explained as:
You may be asking yourself why local variables have these restrictions.
First, there’s a key
difference in how instance and local variables are implemented behind the scenes. Instance
variables are stored on the heap, whereas local variables live on the stack. If a lambda could
access the local variable directly and the lambda were used in a thread, then the thread using the
lambda could try to access the variable after the thread that allocated the variable had
deallocated it. Hence, Java implements access to a free local variable as access to a copy of it
rather than access to the original variable. This makes no difference if the local variable is
assigned to only once—hence the restriction.
Second, this restriction also discourages typical imperative programming patterns (which, as we
explain in later chapters, prevent easy parallelization) that mutate an outer variable.
Because instance variables are always accessed through a field access operation on a reference to some object, i.e. some_expression.instance_variable. Even when you don't explicitly access it through dot notation, like instance_variable, it is implicitly treated as this.instance_variable (or if you're in an inner class accessing an outer class's instance variable, OuterClass.this.instance_variable, which is under the hood this.<hidden reference to outer this>.instance_variable).
Thus an instance variable is never directly accessed, and the real "variable" you're directly accessing is this (which is "effectively final" since it is not assignable), or a variable at the beginning of some other expression.
Putting up some concepts for future visitors:
Basically it all boils down to the point that compiler should be able to deterministically tell that lambda expression body is not working on a stale copy of the variables.
In case of local variables, compiler has no way to be sure that lambda expression body is not working on a stale copy of the variable unless that variable is final or effectively final, so local variables should be either final or effectively final.
Now, in case of instance fields, when you access an instance field inside the lambda expression then compiler will append a this to that variable access (if you have not done it explicitly) and since this is effectively final so compiler is sure that lambda expression body will always have the latest copy of the variable (please note that multi-threading is out of scope right now for this discussion). So, in case instance fields, compiler can tell that lambda body has latest copy of instance variable so instance variables need not to be final or effectively final. Please refer below screen shot from an Oracle slide:
Also, please note that if you are accessing an instance field in lambda expression and that is getting executed in multi-threaded environment then you could potentially run in problem.
It seems like you are asking about variables that you can reference from a lambda body.
From the JLS §15.27.2
Any local variable, formal parameter, or exception parameter used but not declared in a lambda expression must either be declared final or be effectively final (§4.12.4), or a compile-time error occurs where the use is attempted.
So you don't need to declare variables as final you just need to make sure that they are "effectively final". This is the same rule as applies to anonymous classes.
Within Lambda expressions you can use effectively final variables from the surrounding scope.
Effectively means that it is not mandatory to declare variable final but make sure you do not change its state within the lambda expresssion.
You can also use this within closures and using "this" means the enclosing object but not the lambda itself as closures are anonymous functions and they do not have class associated with them.
So when you use any field (let say private Integer i;)from the enclosing class which is not declared final and not effectively final it will still work as the compiler makes the trick on your behalf and insert "this" (this.i).
private Integer i = 0;
public void process(){
Consumer<Integer> c = (i)-> System.out.println(++this.i);
c.accept(i);
}
Here is a code example, as I didn't expect this either, I expected to be unable to modify anything outside my lambda
public class LambdaNonFinalExample {
static boolean odd = false;
public static void main(String[] args) throws Exception {
//boolean odd = false; - If declared inside the method then I get the expected "Effectively Final" compile error
runLambda(() -> odd = true);
System.out.println("Odd=" + odd);
}
public static void runLambda(Callable c) throws Exception {
c.call();
}
}
Output:
Odd=true
YES, you can change the member variables of the instance but you CANNOT change the instance itself just like when you handle variables.
Something like this as mentioned:
class Car {
public String name;
}
public void testLocal() {
int theLocal = 6;
Car bmw = new Car();
bmw.name = "BMW";
Stream.iterate(0, i -> i + 2).limit(2)
.forEach(i -> {
// bmw = new Car(); // LINE - 1;
bmw.name = "BMW NEW"; // LINE - 2;
System.out.println("Testing local variables: " + (theLocal + i));
});
// have to comment this to ensure it's `effectively final`;
// theLocal = 2;
}
The basic principle to restrict the local variables is about data and computation validity
If the lambda, evaluated by the second thread, were given the ability to mutate local variables. Even the ability to read the value of mutable local variables from a different thread would introduce the necessity for synchronization or the use of volatile in order to avoid reading stale data.
But as we know the principal purpose of the lambdas
Amongst the different reasons for this, the most pressing one for the Java platform is that they make it easier to distribute processing of collections over multiple threads.
Quite unlike local variables, local instance can be mutated, because it's shared globally. We can understand this better via the heap and stack difference:
Whenever an object is created, it’s always stored in the Heap space and stack memory contains the reference to it. Stack memory only contains local primitive variables and reference variables to objects in heap space.
So to sum up, there are two points I think really matter:
It's really hard to make the instance effectively final, which might cause lots of senseless burden (just imagine the deep-nested class);
the instance itself is already globally shared and lambda is also shareable among threads, so they can work together properly since we know we're handling the mutation and want to pass this mutation around;
Balance point here is clear: if you know what you are doing, you can do it easily but if not then the default restriction will help to avoid insidious bugs.
P.S. If the synchronization required in instance mutation, you can use directly the stream reduction methods or if there is dependency issue in instance mutation, you still can use thenApply or thenCompose in Function while mapping or methods similar.
First, there is a key difference in how local and instance variables are implemented behind the scenes. Instance variables are stored in the heap, whereas local variables stored in the stack.
If the lambda could access the local variable directly and the lambda was used in a thread, then the thread using the lambda could try to access the variable after the thread that allocated the variable had deallocated it.
In short: to ensure another thread does not override the original value, it is better to provide access to the copy variable rather than the original one.

In Java can making a local variable final in a non-static method that is called many times cause a memory leak?

For example lets say we have:
public void doThis() {
final Foo foo = Foo.getInstance();
... initialize foo somehow...
baz(Bar.getInstance(foo)); // adds Bar instance to something
... bar will be popped from some list, used, and disposed of...
}
Can a memory leak occur for this scenario?
I'm just not understanding what a final local variable really means. Does it just mean that the local variable cannot be reassigned, and that is it? Does declaring it final put it somewhere in the java heap/memory such that it's like an instance variable but with a different/unique? Especially since an inner/nested class can use a final local variable, but not a non-final local variable?
No. If there wasn't a memory leak without final, then there won't be one with final.
The only thing that final does to a local variable (in Java 8)1 is prevent you from assigning to the variable more than once.
1 In Java 7 and earlier, there was another effect which also had nothing to do with memory leaks.
Does it just mean that the local variable cannot be reassigned, and that is it?
Yes it means it behaves like constant variable where further reassignment or modification could not done.
Does declaring it final put it somewhere in the java heap/memory such that it's like an instance variable but with a different/unique?
Final is identifier. This is another variable gets allocated in the java heap. No special memory location available for the
Final variable.
Especially since an inner/nested class can use a final local variable, but not a non-final local variable?
Inner class can access the outer class variable and but it cannot use local variable unless it is declared as Final.
Because the local variables aren't guaranteed to be alive as long as the method-local inner class object, the inner class object can't use them.

Why is a non-static variable not able to be referenced from a static context?

I was just wondering if there is a reason why an object cannot be performed with a non-static variable? I am able to fix the error, (obviously) but I was just wondering why.
static variable initialized when class is loaded into JVM on the other hand instance variable has different value for each instances and they get created when instance of an object is created either by using new() operator or using reflection like Class.newInstance().
So if you try to access a non static variable without any instance compiler will complain because those variables are not yet created and they don't have any existence until an instance is created and they are associated with any instance. So in my opinion only reason which make sense to disallow non static or instance variable inside static context is non existence of instance.
Read more here
If you have a variable which is class-dependant and you try to reference it in a static method it won't compile due to the fact that non-static class variables need an instance to get initialized.
Static elements get initialized automatically into JVM when the class gets loaded - instance variables don't, they're initialized when an instance is created.
Take a look at some Java Docs regarding class variables, it's described in depth in the original Oracle manual. You can start by looking here for example.

How does marking a variable as final allow inner classes to access them?

An inner class defined inside a method cannot access the method's local variables unless these local variables are marked final.I've looked at other posts in stack-overflow and java code ranch but none of them seem to be exactly answering the question as to how marking variables final allows inner class to access local variables in the method.
class MyOuter {
private String x = "Outer";
void fly(final int speed) {
final int e = 1;
class FlyingEquation {
public void seeOuter()
{
System.out.println("Outer x is " + x);
}
public void display()
{
System.out.println(e);// line 1
System.out.println(speed);// line 2
}
}
FlyingEquation f=new FlyingEquation();
f.seeOuter();
f.display();
}
public static void main(String args[])
{
MyOuter mo=new MyOuter();
mo.fly(5);
}
}
Explanations I found to this :
local variables are stored on stack and as soon as the method call finishes the stack is popped up and local variables are inaccessible whereas final local variables are stored in data section of memory potentially allowing JVM to access them even after the end of the method call. Where is the data section of memory ? I believe all local variables final or not are stored on the stack.When the method is removed from the stack the final variable will be removed with it. Is it that the value in the final variable is stored with the object in the heap ?
It does not support non-final fields as they could be changed, either by the method or the class and this is not supported because in reality there are two different fields/variables.
Marking a local variable as final tells the compiler that its value is guaranteed not to change once it has been assigned. This makes it safe for the compiler to create a synthetic field inside the inner class and copy the value of the local variable into this synthetic field when the inner class instance is constructed. All reads of the local variable from inside the inner class code actually compile into reads of the synthetic field instead.
This trick wouldn't work for non-final variables as they might change after the inner class was instantiated, and the synthetic field would get out of sync with the original variable.
It's important to realise that all inner classes are tricks of the compiler - to the runtime JVM all classes (top-level, nested static, and inner) are treated the same.
During instantiation of the inner class, when both the method and the class are in scope, the inner class will make a copy of the variables which are constants, which means that the method can go out of scope, since the inner class is only using a copy of the variable.
Check out this article.
Yes the final local variables are saved on the stack and is destroyed the moment the method is removed from the stack. As #Ian has suggested ,when the compiler sees the final keyword for the variable, it creates a copy of the value in the inner class object on the heap.
The story behind this is that the creators of java didn't have enough time to make full support of closure.
There are several ways to make the language support closure. For example, in scheme, the free parameters in a function are bound to an environment which corresponds to the lexical scope where the function is defined. In a language which forces immutable data such as SML, closure can be implemented by copying the local variables which are needed by the closure to the heap.
So they create inner class to have a poor man's version of closure which mimics the style of ML.
Method Local inner classes can’t use local variable of outer method until that local variable is not declared as final.
The main reason we need to declare a local variable as a final is that local variable lives on stack till method is on the stack but there might be a case the object of inner class still lives on the heap.
checkout this article: http://www.geeksforgeeks.org/inner-class-java/
So now think about it.The local variables of the method live on the stack and exist only for the lifetime of the method. We already know that the scope of a local variable is limited to the method the variable is declared in. When the method ends, the stack frame is blown away and the variable is history. But even after the method completes, the inner class object created within it might still be alive on the heap if, for example, a reference to it was passed into some other code and then stored in an instance variable. Because the local variables aren't guaranteed to be alive as long as the method local inner class object is, the inner class object can't use them. Unless the local variables are marked final.
Does final local variables get stored on a heap instead of stack
?
Explanation: Now after some researching in SO i found out that all local variable (final or not) stored into the stack and go out
of scope when the method execution is over. But about final
variable JVM take these as a constant as they will not change after
initiated . And when a inner class try to access them compiler create
a copy of that variable (not that variable it self) into the heap
and create a synthetic field inside the inner class, so even when
the method execution is over it is accessible because the inner class
has it own copy. Synthetic field are filed which actually doesn't
exist in the source code but compiler create those fields in some
inner classes to make those field accessible. In simple word hidden
field.
So final variable also stored in stack but the copy that variable which a inner class have stored in heap.

Categories

Resources