Core Java

OCA Java 8 Preparation : Lambda Expressions

 

The concept of Lambda expressions and Functional Interface(FI) is itself very large in scope. However, for the OCA Java 8, you are expected to know only the basics of Lambda Expression.

Today, we’ll cover lambda expressions in great details for your Java OCA exam.

To understand why to even use lambda expressions , you can refer this post. It also gives you a gist of a predefined Functional Interface usage – Predicate<T> defined in java.util.function package.

For now, let’s get started.

Functional Interface(FI) :

A functional interface is a Java interface with only one non-Object class abstract method. The abstract method defined within a functional interface is referred to as functional method. Remember below points regarding functional interfaces :

  • You can define any number of methods from java.lang.Object class in a FI.
  • It can also have any number of static and default methods.
  • You can optionally annotate it with @FunctionalInterface. If annotated, the code will fail to compile if we make an attempt to have more than one non-Object class abstract method in a FI.
  • Java 8 introduced many predefined functional interfaces in java.util.function package.
  • Some predefined FI in java.util.function package includes Predicate<T>,Consumer<T>, Function<T,R>, Supplier<T> etc.

Yes, you got it right ! Based on the definition of Functional Interfaces, existing interfaces like Runnable, Comparable etc are also Functional Interfaces.

//compiles fine- equals is from Object class
@FunctionalInterface
interface User{
boolean test(User user);
boolean equals(Object obj);
}

//compiles fine - any number of static and default methods are allowed
@FunctionalInterface
interface User{
boolean test(User user);
default void sayHello(){System.out.println("Hello");}
static void sayBye(){System.out.println("Bye");}
}


//Fails to compile - more than one abstract method(non-Object)
@FunctionalInterface
interface User{
boolean test(User user);
void sayHello();
}

Defining Lambda Expressions:

Lambda expressions implement functional interfaces by defining anonymous functions which can be passed as an argument to some method.

A lambda expression is of the form :

lambda_parameter_list -> lambda_body

There are some interesting rules you need to know when writing a lambda expression.Let’s have a look!

Rules Related to Lambda Parameter List :

  1. The parameter list in a lambda expression is a comma-separated list of formal parameters usually enclosed in parentheses.
    (x,y,z) -> x+y+z;
  2. If we specify the data types of the parameters in the parameter list, they are known as declared-type parameters. Or else when not specified, the parameters are referred as inferred-type parameters.
    //inferred type parameters
    (x,y,z) -> x+y+z;
    
    //declared type parameter
    (int x,int y, int z) -> x+y+z;
  3. In a lambda expression, you can have either all declared-type or all inferred-type parameters. Avoid the mix & match.
  4. When using inferred-type parameters, their type is derived from the type of Functional Interface used by the lambda expression.
    //x and y are integers based on the definition of Predicate<Integer>
    Predicate<Integer> p = (x,y) -> x+y;
    
  5. If you have a single inferred-type parameter in your lambda expression, you can skip the parentheses. Don’t ever try it when having a single declared-type parameter in your lambda expression. Will not work!
    //valid declaration, x is single-inferred type
    x -> System.out.println(x);
    
    //valid declaration, s is single-declared type
    (String s) -> System.out.println(s);
    
    String s -> System.out.println(s); // invalid
  6. When having multiple parameters in the parameter list, use of parentheses is mandatory, irrespective of its type – inferred or declared.
    x,y -> x+y; //is invalid
    
    (x,y) -> x+y; //is valid
    (String x, String y) -> x+y; //valid
  7. Use of modifiers like final is only allowed for declared-type parameters.
    //valid for declared type
    (final int a,int b) -> a+b;
    
    //invalid for inferred type
    (final x, y) -> x+y; //fails to compile

Rules Related to Lambda Body :

  1. A lambda body can be either a single expression or a block of statements.
    //Examples of single-expression body
     a -> System.out.println(a);
    (a,b) -> a+b;
     
    //Examples of block of statements as lambda body
     a -> { System.out.println(a);};
     a -> { System.out.println(a);
          System.out.println(10*a);};
    
  2. Execution of a lambda body can optionally lead to return a value as an output or can even throw an exception.
    //no return type - void
     a -> System.out.println(a); 
    
    a -> null; //compiles fine, returns null
    
    //returns a value
    (a,b) -> a+b;
  3. When a lambda expression is written in form of a ‘single expression’ , don’t use a return keyword. It can only be used within a block of statements.
    (a,b) -> return a+b; //fails to compile
    
    (a,b) -> a+b; //This expression itself means it returns a+b as an output
    
    (a,b) -> {return a+b;}; //compiles fine
  4. If you’re writing your lambda expression as a single expression, it can have any return type – void or non-void . Same is for the block of statements but in that case we write a return statement, if we plan to return some value.
    a -> a++; //non-void return type
    a -> a/=2; //non-void return type
    
    a -> System.out.println(a); // void return type
  5. We must check the compatibility of the function type of the target type and the type of lambda expression.
    //function type : String -> void
    interface DummyFI{
    void sayHello(String txt);
    }
    
    /**The function type of target type and type of
     *lambda expression are compatible 
    *in this example 
    **/
    //type of lambda expression : String -> void  :: compatible
    DummyFI ex1 = s -> System.out.println(txt);
    
    
    /**The function type of target type and type of
     *lambda expression are not compatible 
    *in this example and the code will fail to compile
    **/
    //type of lambda expression : String -> String  :: not - compatible
    DummyFI ex1 = s -> { return "Bye";};
  6. In reference to point 5, if lambda expression is expressed as a ‘single expression’ then the return value of that expression will be ignored if the function type of the target type returns void.
    /* Below code will compile fine
    *  the return value will be simply ignored.
    */ 
    DummyFI obj = s -> new String("Hello");
    

     

Conclusion :

I know this blog post is having a lot of information to digest all at once. But I assure you, going through it a couple of times will make it all clear and things will make sense.

The knowledge gained through this blog post will not only help in scoring well on your Java OCA exam but will also help you professionally as a Java Developer.

I also intend to discuss with you the scope of the lambda expressions but it’s better to cover that topic in a separate post.  So, Stay tuned !

Also, don’t forget to checkout other related Java OCA Exam preparation articles on the blog.

2 comments

Leave a Comment

Your email address will not be published. Required fields are marked *