Saturday, 27 February 2016

Understanding Default methods in Java 8

Background

Based on our knowledge till Java 7 we know that methods in an interface are by default public and abstract and that you cannot have a non abstract method in interface. However this does not hold true from Java 8 with the introduction of default methods. You can declare a method default and provide it's body in the interface itself and you need not implement it in the classes that implement corresponding interface (You can definitely override it though).



Need for default methods

Lets say you have following interface -

public interface Movable {
    String walk();
}

and following class that implements it - 

public class Human implements Movable {

    @Override
    public String walk() {
        return "Human is walking";
    }

}

Now lets say your needs change  and you need to incorporate running as well. You would probably add a run() method in your Movable interface.

public interface Movable {
    String walk();
    String run();
} 

But this will break your Human class as you will have to implement run() method in Human class (or any other class that implements Movable interface). You will get following compilation error - 

  • The type Human must implement the inherited abstract method Movable.run()

To avoid such a situation we can use default methods.

Default Methods in Java 8

To add a default method in interface you need to use default keyword in your method declaration -

public interface Movable {
    String walk();
    default String run() {
        return "Moavable Object is running";
    }
}

and run your class as follows -

public class Human implements Movable {

    @Override
    public String walk() {
        return "Human is walking";
    }
    
    public static void main(String args[]){
        Movable movable = new Human();
        System.out.println(movable.walk());
        System.out.println(movable.run());
    }

}

You will get - 

Human is walking
Moavable Object is running

You can ofcourse override your default method as it suits you but notice that this does not break your existing code.


public class Human implements Movable {

    @Override
    public String walk() {
        return "Human is walking";
    }
    
    @Override
    public String run() {
        return "Human is running";
    }
    
    public static void main(String args[]){
        Movable movable = new Human();
        System.out.println(movable.walk());
        System.out.println(movable.run());
    }

}

And you should get -

Human is walking
Human is running

Multiple interface conflicts

Conflict will arise if you have default method with same signature in two interfaces and a class implements them both - 

public interface A {
    default String testMethod(){
        return "Called from A";
    }
}

public interface B {
    default String testMethod(){
        return "Called from B";
    }
}

public class Test implements A,B {
    public static void main(String args[]) {
        Test test = new Test();
        System.out.println(test.testMethod());
        
    }
}

Above code will not compile with following compilation error -
  • Duplicate default methods named testMethod with the parameters () and () are inherited from the types B and A
Alternatives here would be to override method in the class -

public class Test implements A,B {
    
    @Override
    public String testMethod(){
        return "Called from Test";
    }
    
    public static void main(String args[]) {
        Test test = new Test();
        System.out.println(test.testMethod());
       
    }
}


This should print -
Called from Test


OR if you want implementation of any specific interface you can do -

public class Test implements A,B {
    
    @Override
    public String testMethod(){
        return A.super.testMethod();
    }
    
    public static void main(String args[]) {
        Test test = new Test();
        System.out.println(test.testMethod());
        
    }
}


In this case you will get -
Called from A

NOTE : If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. (JLS)

Though you can specify methods from Object in an interface you cannot override them. For eg. -

    interface A{
        void test();
        default boolean equals (Object obj){    
        }
    }


will fail compilation with -
  • A default method cannot override a method from java.lang.Object 
OR

    interface A{
        void test();
        static boolean equals (Object obj){   
        }
    }


will fail compilation with -
  • This static method cannot hide the instance method from Object

Related Links

Sunday, 21 February 2016

Using Lambda expressions from Java 8 - Part 2

Background

In last post we say what is Lambda expression and how we can use it. In this post we will see some advance topics related to Lambda expression like - 
  • Generic Functional Interfaces
  • Passing Lambda expressions as method arguments
  • Exception handling in Lambda expressions

Generic Functional Interfaces

lambda expression themselves cannot have generics but the functional interface that corresponds to a lambda expression can have generics.

Consider following demo code- 

public class HelloWorld {
    
    public static void main(String args[]) {
        
        MyInterface<String> myStringInterface = (input) -> "Hello " + input;
        MyInterface<Integer> myIntInterface = (input) -> 10 + input;
        
        System.out.println("String based lambda exp : " + myStringInterface.myFunc("OSFG"));
        System.out.println("Integer based labmda exp : " + myIntInterface.myFunc(14));
    }
}

interface MyInterface<T> {
    T myFunc(T t);
}


And the output is -
String based lambda exp : Hello OSFG
Integer based labmda exp : 24


Notice how same method is made generic to operate on both String and Integer inputs.

Passing Lambda expressions as method arguments

Lambda expressions can be sent as method arguments. This makes Java more powerful as you can now send executable code as a part of method argument. Consider following demo code -

public class HelloWorld {
    
    public static void main(String args[]) {
        
        System.out.println("Welcome Lambda : " + executeMyFunc((input)-> "Welcome " + input,"OSFG"));
        System.out.println("Hello Lamda : " + executeMyFunc((input)-> "Hello " + input,"OSFG"));
    }
    
    public static String executeMyFunc(MyInterface myInterface, String input) {
        return myInterface.myFunc(input);
    }

}

interface MyInterface {
    String myFunc(String t);
}

and the output is - 

Welcome Lambda : Welcome OSFG
Hello Lamda : Hello OSFG

Exception handling in Lambda expressions

A lambda expression can throw an exception just like any other method. However if that exception is a checked exception then it should be compatible with the exceptions listed in the throws clause of the abstract method in the corresponding functional interface.

Consider following demo code - 

public class HelloWorld {
    public static void main(String args[]) throws MyException {        
        MyInterface myInterface = (input) -> {
            if(input == null) {
                throw new MyException();
            }
            return "Hello World";
        };
    }
}

interface MyInterface {
    String myFunc(String t) throws MyException;
}


class MyException extends Exception {
    public MyException() {
        super("MyException");
    }
}


NOTE : Here if you abstract method does not throw the checked exception code will fail to compile.

That's it. Let me know if you have any questions on Lambda expressions.

Related Links

Adding Java 8 support to Eclipse kepler

Background

In last post we saw how to use Lambda expressions (well at an introductory level). It is equally important to run it in an IDE like Eclipse to start with. Hence in this post we will see how to compile and run Java 8 compatible code in your Eclipse. Eclipse has a JRE which it uses to compile and run the code and there is compiler compliance level  which basically recognizes your syntax. For example something like below - 

List<String> myList = new ArrayList<>();

won't work with compliance level 6 as the diamond structure was introduced in Java 7. So compliance level 7 is required. We will come to all of this in a moment. This is just a background to get you started. My Eclipse version is Kepler (After upgrading from Juno)- 




NOTE : Eclipse Kepler SR2 & Eclipse Luna are the versions that will support Java 8. Older versions will not (And by not I mean you will see compiler warnings, you can still compile and run if you have Java8 JRE). So of you are using older versions please consider upgrading.

Getting Started

First lets take care of Java compiler compliance level. For that go to Help -> Install new Software



Next add following URL to it and press enter -
  • http://download.eclipse.org/eclipse/updates/4.3-P-builds/
Then select Eclipse java 8 support (for Kepler)



Click Next.Accept TnC and click Finish. Next select 1.8 as compiler compliance level.



You will also need to add JRE 8 as your java runtime (Windows -> Preference -> Installed JREs).



NOTE : Juna 4.4 SR2 already has that. So you can directly download it to save all this migration trouble.

Related Links

Saturday, 20 February 2016

Upgrading Eclipse from Juno to Kepler

Background

In this post I will show you how to upgrade your Eclipse from Juno to Kepler. My current installation details are as follows -



Upgrading Eclipse from Juno to Kepler

  • First you need to add update sites. So go to Windows -> preference. Then search for "Available software sites" and select Add... Then you need to add following 2 sites -
    1. Kepler release repo: http://download.eclipse.org/releases/kepler
    2. Kepler update repo: http://download.eclipse.org/eclipse/updates/4.3
  • Next go to Windows -> Check for Update

  • Previous step may take come time as it checks for new updates. Next select updates as follows -
  • Click Next, accept TnC and click finish to start installation of updates. After installation is complete simply restart Eclipse and you should get Eclipse Kepler.


Using Lambda Expressions from Java 8

Background

It's been some time since Java 8 is out and with it there are some major changes that have come in. Some examples are -
  • Lambda expression
  • Stream collection APIs
  • Functional interfaces etc.
In this post we will see what are Lambda expressions and how we use it in code. 

Introduction

Lambda expression is essentially an anonymous method. But it's not just any method. It is implementation of abstract method that is present in an functional interface. So lambda expression form a kind of anonymous class. Lambda expressions are also called closures.

We said lambda expression essentially implements an abstract method in an functional interface. But what is an functional interface. Functional interface is nothing but an interface with just one abstract method. For example consider interface Runnable . It has a single abstract method run(). So Runnable is a functional interface.

NOTE : A functional interface may specify any public method defined by Object, such as equals( ),
without affecting its “functional interface” status. The public Object methods are considered implicit
members of a functional interface because they are automatically implemented by an instance of a
functional interface.

Lambda expressions and function interfaces

Enough with the introduction. Lets see an example of lambda expression. Consider following interface - 

interface MyInterface {
       int getAge(); 
} 

Does above interface qualify as a functional interface? It certainly does. It just has one method and all methods in an interface and by default public and abstract [Note : There is an exception to this as since Java 8  you can specify default implementation in interface itself but for now I am going to keep default methods away from discussion. We can revisit it in some future post]. Ok So we have a functional interface. Now lets see how we can write a lambda expression for this.

MyInterface myInterface = () -> 24;
System.out.println(myInterface .getAge());

And you should get 24 printed in console. Before we go in the details of this expression lets first look how lambda expression is structure and read. Lambda expression used is - 

  () -> 24
'->' operator is called lambda operator or arrow operator. It divides your lambda expression into two parts. LHS of the operator specifies the arguments of the abstract method of the functional interface. RHS is the body of the method (the return value). RHS can either be a single line or a block of code. The lambda expression is read as "LHS goes to RHS".



NOTE : Single line lambda expressions are called expression lambdas where as the ones with block are called block lambdas.

Difference : Difference between expression and block lambdas is that block lambdas must have a return statement unlike expression lambdas where is it obvious (RHS).

Some more examples

Lets take some more examples to understand this better. Consider following functional interface

interface MyInterface {
       boolean isAllowedAge(int currentAge); 
} 

For this your lambda expression can be -

MyInterface myInterface = (n) -> n>=18;
System.out.println(myInterface.isAllowedAge(4));


Couple of points to note here -

  • Note we are no where specifying the type of n. It is automatically inferred from the functional interface. But if you wish you can specify it -

    MyInterface myInterface = (int n) -> n>=18;
    System.out.println(myInterface.isAllowedAge(4));
    


    However if you specify type of one arguments you should do that for all other arguments. So something like (int n, m) -> n>=m; is not allowed. Also the argument should qualify/match. So something like below wont work


    MyInterface myInterface = (int n) -> "test";   //will not work
    System.out.println(myInterface.isAllowedAge(4));
    
  • If you just have one argument then you don't need parenthesis on the LHS of lambda expression. So you can do something like - 
    MyInterface myInterface = n -> n>=18;
    System.out.println(myInterface.isAllowedAge(4));
    


    But it may get confusing at time. So it is better to always use a parenthesis even if you have one argument :)
Lets see a two argument lambda expression -

Your interface is

interface MyInterface {
       boolean isAllowedAge(int currentAge, int minAge); 
}


and your lambda expression would look something like -

MyInterface myInterface = (n,m) -> n>=m;
System.out.println(myInterface.isAllowedAge(4,5));

Block lambda expression for same interface would look like -

MyInterface myInterface = (n,m) -> {
    int minAge = m;
    if (n >= minAge )
        return true;
    else
        return false;
    }
System.out.println(myInterface.isAllowedAge(4,5));



As you must have noticed you can have local variables, loops, switch statement etc in your block body.

Another good example would be -

Comparator c = (a, b) -> Integer.compare(a.length(), b.length());

OR

Runnable myRunner= () ->{
    System.out.println("I am running");
}; 


NOTE : The default methods introduced in Java 8 do not affect the functional status of an interface. By definition functional interface just has one abstract method. It can have other default methods.

I am going to end up this post here that was intended for lambda expressions introduction. I know there are various follow up topis -

  1. Generic
  2. used as Method arguments
  3. Exception handling

I will come to these topics in subsequent posts.  So stay tuned :)

2nd Part of this tutorial updated -
NOTE  :While it is a good practice to mark a functional interface with the @FunctionalInterface
annotation for clarity, it is not required with functional programming. The Java compiler
implicitly assumes that any interface that contains exactly one abstract method is
a functional interface. Conversely, if a class marked with the @FunctionalInterface
annotation contains more than one abstract method, or no abstract methods at all, then
the compiler will detect this error and not compile.

NOTE : Remember that the parentheses are optional only when there is one parameter and it doesn’t have a type declared.  If you are not using braces you cannot say return something.


NOTE : any public method defined by Object, any default methods or any static methods do not affect the functional status of an functional interface. As long as it has just one abstract method.

 NOTE : If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. (JLS)

NOTE : Main thing to understand about Lambdas is deferred execution. This part of code will be executed at a later point of time.

NOTE : Lambdas use the same access rules as inner classes.
Lambda expressions can access static variables, instance variables, effectively final method parameters, and effectively final local variables. 

Related Links

t> UA-39527780-1 back to top