Monday, August 31, 2015

Java Lambdas with no effectively final variables

In Java the variables that are outside of the scope of the lambdas needs to be effectively final, effectively final is when a variable is declare without the final modifier, but has all the characteristics of a final variable, this means that the variable is declare and initialize, but is never change after the initialization, see the following example:

Final variable declaration into a method:

    public void processWithFinalVariable() {
        List<info> infos = new ArrayList<>();
        final int finalVariable = 0;
        infos.add(new Info("Leonardo"));
     
        // final variable
        infos.forEach( info -> System.out.println("Variable value: " + finalVariable));
    }
Effectively final variable declaration into a method

    public void processWithEffectivelyFinalVariable() {
        List<info> infos = new ArrayList<>();
        int effectivelyFinalVariable = 0;
        infos.add(new Info("Leonardo"));
     
        // effectively final variable
        infos.forEach( info -> System.out.println("Variable value: " + effectivelyFinalVariable));
    }
No effectively final variable declaration into a method

    public void processWithNoEffectivelyFinalVariableChange() {
        List<info> infos = new ArrayList<>();
        int noEffectivelyFinalVariable = 0;
        infos.add(new Info("Leonardo"));
     
        // Compiler error, no effectively final or final variable
        infos.forEach( info -> System.out.println("Variable value: " + noEffectivelyFinalVariable));
     
        noEffectivelyFinalVariable++;
    }
As you can see in the previous examples you are not able to have a variable that is not final or effectively final, the purpose of this post is to show you that we are able to use non final or non effectively final variables in java lambdas.

To have a variable that is not effectively final or final in a lambda expressions you need to declare this variable at the level of the class instance, as you can see in the following example:

public class ExampleObject {
 
    //Instance variable that is not final or effectively final
    private int noEffectivelyFinalVariable = 0;
 
    public void processWithNoEffectivelyFinalVariable() {
        List<info> infos = new ArrayList<>();
     
        infos.add(new Info("Leonardo"));
     
        // See here the variable is able to be modified, is not final or effectively final
        infos.forEach( info -> System.out.println("Variable value: " + noEffectivelyFinalVariable++) );
    }
 
    public void printValue() {
        System.out.println("No Effectively Final Variable: " + noEffectivelyFinalVariable);
    }
}
The previous happened because the compiler adds the "this" java variable to the code that we are using to make the variable reference, and as you know the "this" variable is final by definition, this tell the compiler that is using a final variable and that the lambda is safe, see the following example:  

    public void processWithNoEffectivelyFinalVariableWithExplictThis() {
        List<info> infos = new ArrayList<>();
     
        infos.add(new Info("Leonardo"));
     
        // See here the variable is able to be modified, is not final or effectively final
        infos.forEach( info -> System.out.println("Variable value: " + this.noEffectivelyFinalVariable++) );
    }

Why the previous is possible, the answer is very simple the java compiler just only look up for effectively final variable that are directly reference by the lambda, and not between the compound variables of the effectively or final variable, the "this" variable is final and is a direct reference from the lambda, so the only thing that the compiler does, is to follow the final and effectively final rules and not applying the rules to the compound variables that are in the "this" variable.

The previous is not recommended to be used in your code or in production, because this can create race conditions, and make this kind of errors hard to understand by the developer.

How you can fix the previous:

    Mark the instance variable as final and the compiler will be complaining when it sees this kind of variables and changed from a lambda.

Project source code: ProjectSourceCode

Friday, August 28, 2015

JDK 8 Lambdas MOOC Course Videos and Slides Available

The videos and slides of the JDK 8 Lambdas MOOC online course are available now

In this online course you can see topics as:
  • Lambdas
  • Stream
  • Optional


Enjoy!!!

Tuesday, August 4, 2015

JEP 260: Encapsulate Most Internal APIs

The JEP 260 is a candidate to be included in JDK 9, this JEP deals with the problem that the modularization effort will have with the current internal APIs.

This JEP define three types of internal APIs:

  1. Non critical internal APIs, this are not critical and will be encapsulated in JDK 9
  2. Critical internal APIs witch supported replacement exists, this APIs are critical, but they have a replacement that was made in JDK 8. 
  3. Non encapsulated critical internal APIs, as Unsafe, this APIs does not have a replacement and are critical, this APIs remain public in JDK 9, but as soon as they have a replacement they could be encapsulated. 
If you need more information read the official JEP 260 page.




Revolutionizing Stream Pipelines with Custom Intermediate Operations JEP 473: Stream Gatherers (Second Preview)

Introduction In the ever-evolving scene of Java improvement, the Stream API has been a foundation of utilitarian programming paradigms sin...