I Scoping of “this”
Unlike anonymous functions, a lambda expression can be considered as a simple code block with regarde to variable scoping. Consequently all scoping rules for code blocks also apply to lambda expression.
Let’s look at the below code:
public class MutableObject < private String content = "default_content"; . >public class ScopingOfThis < final public MutableObject mutable = new MutableObject(); public VariableCaptureInClosureSAM createClosure() < VariableCaptureInClosureSAM lambda = ()->< MutableObject mutable = new MutableObject(); mutable.setContent("from_closure"); return this.mutable; >; return lambda; > public VariableCaptureInClosureSAM createAnonymous() < VariableCaptureInClosureSAM anonymousClass = new VariableCaptureInClosureSAM() < MutableObject mutable = new MutableObject(); @Override public MutableObject retrieveMutable() < this.mutable.setContent("from_anonymous"); return this.mutable; >>; return anonymousClass; > public static void main(String[] args) < ScopingOfThis scopingOfThis = new ScopingOfThis(); VariableCaptureInClosureSAM sam = scopingOfThis.createClosure(); MutableObject mutableFromClosure = sam.retrieveMutable(); System.out.println("\nmutableFromClosure content = " + mutableFromClosure.getContent()); MutableObject mutableFromAnonymous = scopingOfThis.createAnonymous().retrieveMutable(); System.out.println("mutableFromAnonymous content = " + mutableFromAnonymous.getContent()); System.out.println(""); >>
At line 17 in the lambda expression, the this keyword is used to distinguish the class level mutable field from the local mutable (“from_closure”) field.
At line 33 in the anonymous class, the this.mutable refers to the mutable field declared in the anonymous class only (line 27)
Not surprisingly, the output gives
mutableFromClosure content = default_content
mutableFromAnonymous content = from_anonymous
Now, what if we declare a local mutable field in the createClosure() method before creating the lambda expression ?
public VariableCaptureInClosureSAM createClosure() < MutableObject mutable = new MutableObject(); VariableCaptureInClosureSAM lambda = ()->< MutableObject mutable = new MutableObject(); mutable.setContent("from_closure"); return this.mutable; >; return lambda; >
The compilation will fail with the error
ScopingOfThis.java:16: error: variable mutable is already defined in method createClosure()
MutableObject mutable = new MutableObject();
^
No surprise here. As in a normal code block you cannot declare a local variable with the same name (the type doesn’t matter) if it already exists in the current lexical scope.
The above code example can be found on GitHub at https://github.com/doanduyhai/Java8_Lambda_In_Details. Just execute the ScopingOfThis.bat(ScopingOfThis.sh) script
II “Effectively final” semantic for local variables
In the JDK 7, variable from enclosing class can be used in anonymous functions only if they are declared final. With the JDK 8 this constraint has been relaxed both for lambda expressions and inner classes. It is so called “effectively final” if the variable initial value does not change. But what is the initial value ? It is its reference ? Is it its state ? The litterature is very vague about the fact (http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.htm chapter 7)
The best way to clarify it is testing.
public class LocalEffectivelyFinalVariable < public VariableShadowingSAM retrieveVariableShadowingSAM() < ListtextList = new ArrayList(); textList.add("default"); VariableShadowingSAM sam = () -> < return textList.get(0); >; textList.clear(); textList.add("changed_default"); return sam; > public static void main(String. args) < LocalEffectivelyFinalVariable variableShadowing = new LocalEffectivelyFinalVariable(); String text = variableShadowing.retrieveVariableShadowingSAM().process(); System.out.println("\n\n\ttext = " + text); System.out.println(""); >>
In the above code, after initializing the list with “default” (line 6), the lambda expression is created and returns the first element of this list (line 9).
Right after lambda declaration, the list is cleared and initialized to “changed_default” (lines 12-13).
How is the local “effectively final” textList variable captured ? 2 implementations are possible:
- either the lambda catures the reference on the returned object, which is the “default” string (testList.get(0)). It means that any subsequent change in the textList would not affect the returned value at runtime
- or the lambda only captures the reference on the textList variable and delays get(0) invocation at runtime. This second implementation makes the returned value unpredictable since the textList can be changed after lambda definition
text = changed_default
This result clearly demonstrates that the second implementation has been chosen for JDK 8. The lambda only keeps the reference on local variable and method invocation is performed at runtime !
Now what if we change the reference on the textList variable after lambda expression creation ?
public VariableShadowingSAM retrieveVariableShadowingSAM() < ListtextList = new ArrayList(); textList.add("default"); VariableShadowingSAM sam = () -> < return textList.get(0); >; textList = new ArrayList(); textList.add("new_instance"); return sam; >
This result confirms our previous analysis. The lambda keeps the reference on the old textList instance. Even though the local textList has been assigned a new instance of ArrayList with a “new_instance” value, the lambda execution at runtime still displays “default“.
This is the true meaning of “effectively final”. The lambda capture the reference of your local variable in its declaration. No matter how the variable is assigned a new reference afterward, the old reference is still hold by the lambda. It is as if the variable was declared final in the end.
It is interesting to compare JDK 8 closure implementation with Javascript implementation. If you’re familiar with Javascript internals you should know that a closure in Javascript keeps reference to the local variables through scope chain.
function getClosure() < var text="default"; var closure = function() < return text; >text="changed_default"; return closure; >
At runtime, when the closure is invoked, it will look for the text variable in its scope chain. Since the getClosure function (object) is in the chain, the text reference is returned. The displayed value corresponds to the last known value for text, which was “changed_default“.
It is very similar to the capture of the this reference by lambda expression in Java discussed in the previous article.
Java this Keyword
In the above program, the instance variable and the parameter have the same name: age. Here, the Java compiler is confused due to name ambiguity.
In such a situation, we use this keyword. For example,
First, let’s see an example without using this keyword:
class Main < int age; Main(int age)< age = age; >public static void main(String[] args) < Main obj = new Main(8); System.out.println("obj.age java-exec">class Main < int age; Main(int age)< this.age = age; >public static void main(String[] args) Now, we are getting the expected output. It is because when the constructor is called, this
inside the constructor is replaced by the object obj that has called the constructor. Hence the age variable is assigned value 8.
Also, if the name of the parameter and instance variable is different, the compiler automatically appends this keyword. For example, the code:
class Main < int age; Main(int i) < age = i; >>
this with Getters and Setters
Another common use of this keyword is in setters and getters methods of a class. For example:
class Main < String name; // setter method void setName( String name ) < this.name = name; >// getter method String getName() < return this.name; >public static void main( String[] args ) < Main obj = new Main(); // calling the setter and the getter method obj.setName("Toshiba"); System.out.println("obj.name: "+obj.getName()); >>
Here, we have used this keyword:
Using this in Constructor Overloading
While working with constructor overloading, we might have to invoke one constructor from another constructor. In such a case, we cannot call the constructor explicitly. Instead, we have to use this keyword.
Here, we use a different form of this keyword. That is, this() . Let's take an example,
class Complex < private int a, b; // constructor with 2 parameters private Complex( int i, int j )< this.a = i; this.b = j; >// constructor with single parameter private Complex(int i) < // invokes the constructor with 2 parameters this(i, i); >// constructor with no parameter private Complex() < // invokes the constructor with single parameter this(0); >@Override public String toString() < return this.a + " + " + this.b + "i"; >public static void main( String[] args ) < // creating object of Complex class // calls the constructor with 2 parameters Complex c1 = new Complex(2, 3); // calls the constructor with a single parameter Complex c2 = new Complex(3); // calls the constructor with no parameters Complex c3 = new Complex(); // print objects System.out.println(c1); System.out.println(c2); System.out.println(c3); >>
In the above example, we have used this keyword,
- to call the constructor Complex(int i, int j) from the constructor Complex(int i)
- to call the constructor Complex(int i) from the constructor Complex()
Here, when we print the object c1 , the object is converted into a string. In this process, the toString() is called. Since we override the toString() method inside our class, we get the output according to that method.
One of the huge advantages of this() is to reduce the amount of duplicate code. However, we should be always careful while using this() .
This is because calling constructor from another constructor adds overhead and it is a slow process. Another huge advantage of using this() is to reduce the amount of duplicate code.
Note: Invoking one constructor from another constructor is called explicit constructor invocation.
Passing this as an Argument
We can use this keyword to pass the current object as an argument to a method. For example,
Table of Contents
Variable Scope
Knowing when you can use a variable gets confusing if you don't understand variable scope. Have you ever seen the same variable name in two different places in a piece of Java code, but they held different values? Have you ever tried to use a variable and had the Java compiler yell at you because you apparently have no reference to the variable in your context? Again, this all has to do with variable scope and this tutorial will help to uncover the mystery of scope in Java.
Class Level Scope
In Java, there are some variables that you want to be able to access from anywhere within a Java class. The scope of these variables will need to be at the class level, and there is only one way to create variables at that level – just inside the class but outside of any methods. Let's take a look at an example:

You will notice that the variables have been defined at the top of the class, before any methods. This is simply a convention; you can define your class-level variables anywhere in the class (so long as it's outside of any methods in the class). However, it is good practice to put these variables at the top so it's easier to see where they all are. Also note that the access identifier does not have anything to do with the variable's scope within the class! If you're not sure what access identifiers are, I strongly recommend checking out our tutorial about them by clicking here.
Method Scope
Some variables you might want to make temporary and preferably they are used for only one method. This would be an example of method scope. Here's a pretty typical example of a variable in method scope using an example of Java's main method:

The variable x in the example is created inside the method. When the method ends, the variable reference goes away and there is no way to access that variable any longer. You cannot use that same variable x in another method because it only exists in the main method's scope and that is it.
Here's another example of method scope, except this time the variable got passed in as a parameter to the method:

The above example is the typical example of a setter method. The purpose of a setter method as you might recall is to set a class variable to a particular value from somewhere outside of the class. The above example is a pretty clean example of this. Now let's look at the same example, except now we'll use a conflicting variable name.

So, what's going on with the variable scope here? And what is "this"? The this keyword helps Java to differentiate between the local scope variable (the method scope variable) and the class variable. This.username tells Java that you are referencing the class variable. So, the setter above sets the method-scope variable called name to the class variable called name. The variable scope here is not in conflict because Java knows which variable to access because of the "this" keyword. You could also do this:

However the above is something you probably won't be doing often (if at all!) because you're setting the local, temporary variable to the value of the more permanent one.
Loop Scope
Have you ever had trouble accessing a variable when dealing with for loops and while loops? Variable scope plays a big role in your difficulty, so let's figure out what's going on there.
Any variables created inside of a loop are LOCAL TO THE LOOP. This means that once you exit the loop, the variable can no longer be accessed! This includes any variables created in the loop signature. Take a look at the following two for loop examples:


In the first example, x can ONLY be used inside of the for loop. In the second example, you are free to use x inside of the loop as well as outside of the loop because it was declared outside of the loop (it has been declared at method scope).
A quick hint about variable scope in Java:
In general, a set of curly brackets < >defines a particular scope. In Java you can usually access a variable as long as it was defined within the same set of brackets as the code you are writing or within any curly brackets inside of the curly brackets where the variable was defined.
Hopefully this helps to clarify variable scope in Java. Many people get confused about this topic because it's never explained properly. If there are examples that are confusing in this tutorial, free free to contact me and let me know!
If you would like to leave a comment or have a question about our Variable Scope tutorial, please click here or visit the Contact Us sidebar link to fill out our contact us form. Thanks!