Java 8 has introduced a new feature called Lambda expressions.It is considered to be a major change in java. As this change will bring functional programming into java. Other languages such as Scala already have this feature so this is not new to programming world, it is new to java.

Before understanding Lambda expressions, Lets first understand Functional Interface.

What is Functional Interface?

Functional interfaces are those interfaces which have only one abstract method in it. It can have more than one default or static method and can override method from java.lang.object. Lets create a functional interface:
@FunctionalInterface
public interface Decorable {

 // one abstract method
 void decorateWithCurtains();
 
 // default method
 default void decorateWithPaints()
 {
  System.out.println("Decorating using paints");
 }

 // Overriding method of java.lang.Object
 @Override
 public int hashCode();

} 

Java can itself identify Functional Interface but you can also denote interface as Functional Interface by annotating it with @FunctionalInterface.

Some popular Functional Interfaces are:
  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.awt.event.ActionListener
  • java.util.Comparator

Why Lambda Expressions?

Lets understand with help of  Anonymous Comparator:
         Country indiaCountry=new Country(1, "India");
         Country chinaCountry=new Country(4, "China");
         Country nepalCountry=new Country(3, "Nepal");
         Country bhutanCountry=new Country(2, "Bhutan");
        
         List<Country> listOfCountries = new ArrayList<Country>();
         listOfCountries.add(indiaCountry);
         listOfCountries.add(chinaCountry);
         listOfCountries.add(nepalCountry);
         listOfCountries.add(bhutanCountry); 

         //Sort by countryName

            Collections.sort(listOfCountries,new Comparator<Country>() {

                @Override
                public int compare(Country o1, Country o2) {

                    return o1.getCountryName().compareTo(o2.getCountryName());
                }
            });

The problem with Anonymous Comparator is of syntax. Each time you want to sort list using comparator, you have to remember bulky syntax.
So generally main problem with Anonymous classes are syntax.For very simple operation, we need to write complex code. To solve this problem, JDK has introduce new feature called Lambda Expressions.I will take this example after explaining lambda expression to understand , how lambda expression will reduce this complex code.

What is Lambda Expressions:

lambda expression represents an anonymous function. It comprises of a set of parameters, a lambda operator (->) and a function body .You can call it function without name,

Connection between Lambda Expression and Functional Interface:
You might be thinking I have introduced functional Interface above but how it is connected to Lambda.So Lambda expression can be applied for abstract method of functional Interface which is being implemented or being instantiated anonymously.

Structure of Lambda Expressions

(Argument List) ->{expression;} or
(Argument List) ->{statements;}  

So we can divide structure of Lambda expression to three parts:
  1.  Argument list or parameters
    • Lambda expression can have zero or more arguments.
      ()->{System.out.println("Hello")}; //Without argument, will print hello 
      (int a)->{System.out.println(a)} //; One argument, will print value of a
      (int a,int b)-> {a+b};//two argument, will return sum of these two integers
      
      
    • You can choose to not declare type of arguments as it can be inferred from context.
    • (a,b)->{a+b};//two argument, will return sum of these two numbers
    • you can not declare one argument's type and do not declare type for other argument. 
    • (int a,b)->{a+b};//Compilation error 
    • When there is a single parameter, if its type is inferred, it is not mandatory to use parentheses
      a->{System.out.println(a)}; // Will print value of number a 
  2. Array token (->)
  3. Body
    • Body can have expression or statements.
    • If there is only one statement in body,curly brace is not needed and return type of the anonymous function is same as of  body expression
    • If there are more than one statements, then it should be in curly braces and return type of anonymous function is same as value return from code block, void if nothing is returned.
Lets take some examples ,  you want to initialize thread and now you will realize, how can lambda expression can make your coding easy :
public class ThreadSample {

 public static void main(String[] args) {
  
  // old way
  new Thread(new Runnable() {
   
   @Override
   public void run() {
    System.out.println("Thread is started");
   }
  }).start();

  // using lambda Expression
  new Thread(()->System.out.println("Thread is started")).start();
 }

}

Lets take another example of Comparator which we have seen in Anonymous Comparator in java.
Create a class called Country.java
package org.arpit.java2blog;

public class Country{
    int countryId;
    String countryName;
    
    public Country(int countryId, String countryName) {
        super();
        this.countryId = countryId;
        this.countryName = countryName;
    }

    public int getCountryId() {
        return countryId;
    }
    public void setCountryId(int countryId) {
        this.countryId = countryId;
    }
    public String getCountryName() {
        return countryName;
    }
    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }
} 
Create a main class called ComparatorMain.java
package org.arpit.java2blog;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComparatorMain {

 /**
  * @author Arpit Mandliya
  */
 public static void main(String[] args) {
  Country indiaCountry=new Country(1, "India");
  Country chinaCountry=new Country(4, "China");
  Country nepalCountry=new Country(3, "Nepal");
  Country bhutanCountry=new Country(2, "Bhutan");

  List<country> listOfCountries = new ArrayList<country>();
  listOfCountries.add(indiaCountry);
  listOfCountries.add(chinaCountry);
  listOfCountries.add(nepalCountry);
  listOfCountries.add(bhutanCountry);

  System.out.println("Before Sort by name : ");
  for (int i = 0; i < listOfCountries.size(); i++) {
   Country country=(Country) listOfCountries.get(i);
   System.out.println("Country Id: "+country.getCountryId()+"||"+"Country name: "+country.getCountryName());
  }

  //Sort by countryName
  // Anonymous Comparator
  // old way
  Collections.sort(listOfCountries,new Comparator<country>() {

   @Override
   public int compare(Country o1, Country o2) {
    return o1.getCountryName().compareTo(o2.getCountryName());
   }
  });
  
  // Using lambda expression
  Collections.sort(listOfCountries,(o1,o2)-> o1.getCountryName().compareTo(o2.getCountryName()));
  
  System.out.println("After Sort by name: ");
  for (int i = 0; i < listOfCountries.size(); i++) {
   Country country=(Country) listOfCountries.get(i);
   System.out.println("Country Id: "+country.getCountryId()+"|| "+"Country name: "+country.getCountryName());
      
   }
 }

}
As you can see here, we have used lambda expression for using Comparator. SO inspite of wrting Anonymous comparator, our expression became very easy.









So we have passed 2 arguments o1 and o2, we didn't pass type because it can inferred from context.
We have only one statement here, so no need to put it in curly braces.

Lets create HelloWorld Lambda Expression Example:

Create an Interface Called HelloWorld:
package org.arpit.java2blog;

public interface HelloWorld {
 void sayHello();
}

Create a class called HelloWorldMain
package org.arpit.java2blog;

public class HelloWorldMain {

 public static void main(String args[])
 {
                // Lambda Expression 
  HelloWorld helloWorld=()->System.out.println("Hello using Lambda Expression");
  helloWorld.sayHello();
 }
}
Run above program you will get following output:
Hello using Lambda Expression
Hope you understand Lambda expression now, in next post, we will see more examples of it.

In this post, I will introduce default methods in interface which are introduced in  Java 8.
Have you ever faced a situation, when you created an interface and many classes implemented that interface and now you have need to add new methods to interface. After adding new methods, your java project will be full of compilation errors because you need to add these new methods to all classes which were implementing that interface as if a class implement an  interface then you have to implement all its methods in the class.
Lets take an example:
Create an interface called Decorable
public interface Decorable {
    void decorateWithCurtains();
    }
Now Create a class called Room which will implement this interface.
public class Room implements Decorable{
    public void decorateWithCurtains() {
        System.out.println("Decorate room with Curtains");
    }
}
Now this was your current implementation and now you have a new way of decorating and you want to add it to Decorable inteface.When you add this method to Decorable interface
public interface Decorable {

    void decorateWithCurtains();
    void decorateWithPaints();
 } 
In Room class, you will get following error:

What if We use default method:

public interface Decorable {
    void decorateWithCurtains();
    default void decorateWithPaints()
    {
           System.out.println("Decorate using paints");
    }
  }
As you can see, we have made decorateWithPaints() default and we will not get any error in Room class as we have provided default implementation in Decorable interface.

Why default methods

The oneliner for this could be "backward compatibility".If JDK modifies an interface, then all classes which implements this interface will break.

For adding lambda expression in Java 8, JDK needs to add  methods(such as foreach) to List or collections Interface, but if you add this method to these interface, it will break millions lines of code as class which implements the interface, need to implement all its methods.

By adding default method in interface, you can provide default implementation of it without affecting implementing classes as it includes implementation of that method and any implementing class which needs that method can override it.

What about multiple Inheritance?

Adding default implementation to the interface can give rise to ambiguity in multiple inheritance. As two interface can provide same default method and there can be ambiguity while calling.Java 8 will give you compile time exception when this kind of situation will arise.
public interface Decorable {
    default void decorateWithPaints()
    {
       System.out.println("Decorate using paints");
    }
   }

public interface Paintable
{
    default void decorateWithPaints()
    {        
        System.out.println("Decorate using paints");  
    }
}

public class Room implements Decorable,Paintable{
    }
so it will give you compile time error as below:
you can solve this compilation error by overriding decorateWithPaints method in Room class
public class Room implements Decorable,Paintable{

    public void decorateWithPaints()
    {       
        System.out.println("Decorate using paints");  
  }
}

Difference between default methods and abstract class

Introduction of default methods to interface bridge gap between interface and abstract class.Now interface looks very similar to abstract classes but there are still differences. Lets list them

Parameter
Abstract class
Interface with default methods
State of objects
Abstract class can hold state of object
Interface with default methods can not hold state of objects
Access Modifier
Abstract class methods can have public ,protected,private and default modifier
Interface methods are by default public. you can not use any other access modifier with it
Constructor
Abstract class can have constructor
Interface  can not have constructor
Member variables
It can have member variables
It can not have member variable

Some of the popular interview questions are "What are differences between abstract class and interface". "When will you use abstract class and when will you use interface". So in this article ,we will go through this topic.

Before going through differences between them, Lets go through its introduction.

Abstract class:

Abstract classes are created to capture common characteristics of subclasses. It can not be instantiated, it can be only used as super class by its subclasses. Abstract classes are used to create template  for its sub classes down the hierarchy.
Lets take example of JDK class GenericServlet
public abstract class GenericServlet implements  Servlet, ServletConfig,Serializable{    
// abstract method     
    abstract  void     service(ServletRequest req, ServletResponse res) ; 
    void init()     {
         // Its implementation        
     }  
       // other method related to Servlet    
}
When HttpServlet extends Generic servlet, it provides implementation of service() method
public class HttpServlet extends GenericServlet
{
       void  service(ServletRequest req, ServletResponse res)
       {
       // implementation 
}
     protected  void  doGet(HttpServletRequest req, HttpServletResponse resp) 
{
    // Implementation 
}

   protected  void  doPost(HttpServletRequest req, HttpServletResponse resp) 
{
    // Implementation 
}

// some other methods related to HttpServlet
}

Interface:

An interface is a collection of abstract methods. A class implements an interface, thereby inheriting the abstract methods of the interface. So it is kind of signing a contract,you agree that if you implement this interface, then you have to use its methods.It is just a pattern, it can not do anything itself.
Lets take example of Externalizable Interface.
public interface Externalizable
extends Serializable
{

    void writeExternal(ObjectOutput out)
            throws IOException;
    void readExternal(ObjectInput in)
            throws IOException,
            ClassNotFoundException;
} 

When you implement this interface, you have to implement above two methods.
public class Employee implements Externalizable{ 

 int employeeId;
 String employeeName;


 @Override
 public void readExternal(ObjectInput in) throws IOException,
 ClassNotFoundException {  employeeId=in.readInt();
  employeeName=(String) in.readObject();
  
 } @Override
 public void writeExternal(ObjectOutput out) throws IOException {

  out.writeInt(employeeId);
  out.writeObject(employeeName); }
}


Abstract class vs Interface

Parameter
Abstract class
Interface
Default method Implementation
It can have default method implementation
Interfaces are pure abstraction.It can not have implementation at all but in java 8, you can have default methods in interface.
Implementation
Subclasses use extends keyword to extend an abstract class and they need to provide implementation of all the declared methods in the abstract class unless the subclass is also an abstract class
subclasses use implements keyword to implement interfaces and should provide implementation for all the methods declared in the interface
Constructor
Abstract class can have constructor
Interface  can not have constructor
Different from normal java class
Abstract classes are almost same as java classes except you can not instantiate it.
Interfaces are altogether different type
Access Modifier
Abstract class methods can have public ,protected,private and default modifier

Interface methods are by default public. you can not use any other access modifier with it
Main() method
Abstract classes can have main method so we can run it

Interface do not have main method so we can not run it.
Multiple inheritance
Abstract class can extends one other class and can implement one or more interface.

Interface can extends to one or more interfaces only
Speed
It is faster than interface
Interface is somewhat slower as it takes some time to find implemented method in class
Adding new method
If you add new method to abstract class, you can provide default implementation of it. So you don't need to change your current code

If you add new method to interface, you have to change the classes which are implementing that interface

When to use Abstract class and interface:

  • If you have lot of methods and want default implementation for some of them, then go with abstract class
  • If you want to implement multiple inheritance then you have to use interface.As java does not support multiple inheritance, subclass can not extend more than one class but you can implement multiple interface so you can use interface for that.
  • If your base contract keeps on changing then you should use an abstract class. Because if your base contract keeps on changing and you still use an interface, you would have to change all the classes which implements that interface every time the contract changes.

Introduction of default and static methods in java 8

Oracle has tried to bridge gap between abstract class and interface by introducing concept of default and static methods in interface.So now we can provide default implementation of a method in interface and will not enforce class to implement it. I will cover these topic in my next post.

Please go through  core java interview questions for more interview questions.

In this post, we will see  how you can use comparable to sort list of objects in java.

Comparable interface:

Class whose objects to be sorted must implement this interface.In this,we have to implement compareTo(Object) method.
For example:
public class Country implements Comparable<Country>{
       @Override
    public int compareTo(Country country) {
        return (this.countryId < country.countryId ) ? -1: (this.countryId > country.countryId ) ? 1:0 ;
}} 
If any class implements comparable inteface then collection of that object can be sorted automatically using Collection.sort() or Arrays.sort().Object will be sort on the basis of compareTo method in that class.
Objects which implement Comparable in java can be used as keys in a SortedMap like TreeMap or SortedSet like TreeSet without implementing any other interface.

Sorting logic must be in same class whose objects are being sorted. Hence this is called natural ordering of objects

Java code: 

For Comparable:

We will create class country having attribute id and name.This class will implement Comparable interface and implement CompareTo method to sort collection of country object by id.

1. Country.java
package org.arpit.java2blog;
//If this.cuntryId < country.countryId:then compare method will return -1
//If this.countryId > country.countryId:then compare method will return 1
//If this.countryId==country.countryId:then compare method will return 0
public class Country implements Comparable<Country>{
    int countryId;
    String countryName;
   
   
    public Country(int countryId, String countryName) {
        super();
        this.countryId = countryId;
        this.countryName = countryName;
    }

    @Override
    public int compareTo(Country country) {
       return (this.countryId < country.countryId ) ? -1: (this.countryId > country.countryId ) ? 1:0 ;
    }


    public int getCountryId() {
        return countryId;
    }


    public void setCountryId(int countryId) {
        this.countryId = countryId;
    }


    public String getCountryName() {
        return countryName;
    }


    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }
   
}
2.ComparableMain.java
package org.arpit.java2blog;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparableMain {

 /**
  * @author Arpit Mandliya
  */
 public static void main(String[] args) {
   Country indiaCountry=new Country(1, "India");
   Country chinaCountry=new Country(4, "China");
   Country nepalCountry=new Country(3, "Nepal");
   Country bhutanCountry=new Country(2, "Bhutan");
   
         List<Country> listOfCountries = new ArrayList<Country>();
         listOfCountries.add(indiaCountry);
         listOfCountries.add(chinaCountry);
         listOfCountries.add(nepalCountry);
         listOfCountries.add(bhutanCountry);
  
         System.out.println("Before Sort  : ");
         for (int i = 0; i < listOfCountries.size(); i++) {
    Country country=(Country) listOfCountries.get(i);
    System.out.println("Country Id: "+country.getCountryId()+"||"+"Country name: "+country.getCountryName());
   }
         Collections.sort(listOfCountries);
         
         System.out.println("After Sort  : ");
         for (int i = 0; i < listOfCountries.size(); i++) {
    Country country=(Country) listOfCountries.get(i);
    System.out.println("Country Id: "+country.getCountryId()+"|| "+"Country name: "+country.getCountryName());
   }
 }

}
 
Output:
Before Sort  : 
Country Id: 1||Country name: India
Country Id: 4||Country name: China
Country Id: 3||Country name: Nepal
Country Id: 2||Country name: Bhutan
After Sort  : 
Country Id: 1|| Country name: India
Country Id: 2|| Country name: Bhutan
Country Id: 3|| Country name: Nepal
Country Id: 4|| Country name: China 

If two or more methods have same name , but different argument then it is called method overloading.

Why you would do that (same name but different argument)?

Lets take an example. You want to print salary of employee and sometimes company gives bonus to their employee and sometimes it don't.So If company don't give bonus then we can use printSalary(int salary) method and if it provides bonus then we can use printSalary(int salary,int bonus) so both methods are doing same work but their inputs are different so it will increase readability of programs.Otherwise if you give different methods name,it will become hard to understand.

package org.arpit.java2blog;

public class Employee{
    
    public void printSalary(int salary)
    {
        System.out.println("Salary without bonus : "+salary);
        
    }
    
    public void printSalary(int salary,double bonus)
    {
        System.out.println("Salary with bonus : "+(salary+bonus));
        
    }
    public static void main(String args[])
    {
        
        Employee e1=new Employee();
        // if no bonus provided, we can use this method
        e1.printSalary(20000);
        System.out.println("**********************");
        // If bonus provided we can pass to overloaded method and add to salary
        e1.printSalary(20000, 10000);
    }
}


When you run above program, you will get following output:
Salary without bonus : 20000
**********************
Salary with bonus : 30000

Rules of Method overloading :


Number of Arguments
Overloaded method can have different number of arguments
Date type Overload method can have different data type for argument
Return type

Return type can be changed but either number of argument or data type of argument should also be changed..
Order of argumentsIf you change sequence of arguments then it is also valid method overloading provided you have different data types arguments.
ConstructorCan be overloaded

So you can overload method using three ways:
  1. By changing number of arguments
  2. By changing data type of arguments
  3. By changing sequence of arguments if they are of different types

By changing number of arguments:

Above example which we have taken is of this type.We are overloading printSalary() method with different number of argument.

By changing data type of arguments:

In above example, we will create another method, which will take double data type as input.
package org.arpit.java2blog;
public class Employee{
    
    public void printSalary(int salary)
    {
        System.out.println("Salary without bonus : "+salary);
        
    }
    
    public void printSalary(int salary,double bonus)
    {
        System.out.println("Salary with bonus : "+(salary+bonus));
        
    }

  public void printSalary(double salary)    {
        System.out.println("Salary without bonus : "+salary);
        
    }

    public static void main(String args[])

    {
        
         Employee e1=new Employee();
        // if no bonus provided, we can use this method
        //will call printSalary(int)
        e1.printSalary(20000);
        Employee e2=new Employee();
        // will call printSalary(double)
        e2.printSalary(30000.5);
        System.out.println("**********************");
        // If bonus provided we can pass to overloaded method and add to salary
        e1.printSalary(20000, 10000);
    }
}

 so here we have introduced a new method which takes double datatype as input.This is also valid method overloading.

By changing sequence of argument if they are of different data types:

We can introduce a new method printSalary(double bonus,int salary). so by changing order of argument we can overload method.
package org.arpit.java2blog;

public class Employee{
    
    public void printSalary(int salary)
    {
        System.out.println("Salary without bonus : "+salary);
        
    }
    
    public void printSalary(int salary,double bonus)
    {
        System.out.println("Salary with bonus : "+(salary+bonus));
        
    } 
 public void printSalary(double bonus,int salary)
    {
        System.out.println("Salary with bonus : "+(salary+bonus));
        
    }


    public static void main(String args[])
    {
        
        Employee e1=new Employee();
        // if no bonus provided, we can use this method
        e1.printSalary(20000);
        System.out.println("**********************");
        // If bonus provided we can pass to overloaded method and add to salary
        e1.printSalary(20000, 10000);<
      // Changing sequence 
        e1.printSalary(2000.5, 20000); 
    }

}

Why we can't change only return type?

 If we change only return type, it will become ambiguous for compiler to figure out which method to call.That is why you can not change only return type.

What is static binding? 

When you compile Java program. During compilation process, compiler bind method call to actual method. This is called static binding and method overloading binding happens at compile time.

In this post, we will see  how you can use comparator to sort list of objects in java.

Comparator:

When you want to sort list of objects of a class.You can use Comparator interface. Class whose objects to be sorted do not need to implement this interface.Some third class can implement this interface to sort.e.g.CountrySortByIdComparator class can implement Comparator interface to sort collection of country object by id. For example:
public class CountrySortByIdComparator implements Comparator<Country>{

    @Override
    public int compare(Country country1, Country country2) {
        
        return (country1.getCountryId() < country2.getCountryId() ) ? -1: (country1.getCountryId() > country2.getCountryId() ) ? 1:0 ;
    }

}
Using Comparator interface,we can write different sorting based on different attributes of objects to be sorted.You can use anonymous comparator to compare at particular line of code.We will see more about it later. For example:
         Country indiaCountry=new Country(1, "India");
         Country chinaCountry=new Country(4, "China");
         Country nepalCountry=new Country(3, "Nepal");
         Country bhutanCountry=new Country(2, "Bhutan");
        
         List<Country> listOfCountries = new ArrayList<Country>();
         listOfCountries.add(indiaCountry);
         listOfCountries.add(chinaCountry);
         listOfCountries.add(nepalCountry);
         listOfCountries.add(bhutanCountry); 

 //Sort by countryName

            Collections.sort(listOfCountries,new Comparator<Country>() {

                @Override
                public int compare(Country o1, Country o2) {

                    return o1.getCountryName().compareTo(o2.getCountryName());
                }
            });

Java code for Comparator:

We will create class country having attribute id and name and will create another class CountrySortByIdComparator which will implement Comparator interface and implement compare method to sort collection of country object by id.

1.Country.java

package org.arpit.javapostsforlearning;

public class Country{
    int countryId;
    String countryName;
    
    public Country(int countryId, String countryName) {
        super();
        this.countryId = countryId;
        this.countryName = countryName;
    }

    public int getCountryId() {
        return countryId;
    }


    public void setCountryId(int countryId) {
        this.countryId = countryId;
    }


    public String getCountryName() {
        return countryName;
    }


    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }
    
} 
2.CountrySortbyIdComparator.java
package org.arpit.javapostsforlearning;

import java.util.Comparator;
//If country1.getCountryId()<country2.getCountryId():then compare method will return -1
//If country1.getCountryId()>country2.getCountryId():then compare method will return 1
//If country1.getCountryId()==country2.getCountryId():then compare method will return 0
 public class CountrySortByIdComparator implements Comparator<Country>{

    @Override
    public int compare(Country country1, Country country2) {
        
        return (country1.getCountryId() < country2.getCountryId() ) ? -1: (country1.getCountryId() > country2.getCountryId() ) ? 1:0 ;
    }

}
3.ComparatorMain.java

package org.arpit.javapostsforlearning;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComparatorMain {

 /**
  * @author Arpit Mandliya
  */
 public static void main(String[] args) {
   Country indiaCountry=new Country(1, "India");
   Country chinaCountry=new Country(4, "China");
   Country nepalCountry=new Country(3, "Nepal");
   Country bhutanCountry=new Country(2, "Bhutan");
   
         List<Country> listOfCountries = new ArrayList<Country>();
         listOfCountries.add(indiaCountry);
         listOfCountries.add(chinaCountry);
         listOfCountries.add(nepalCountry);
         listOfCountries.add(bhutanCountry);
  
         System.out.println("Before Sort by id : ");
         for (int i = 0; i < listOfCountries.size(); i++) {
    Country country=(Country) listOfCountries.get(i);
    System.out.println("Country Id: "+country.getCountryId()+"||"+"Country name: "+country.getCountryName());
   }
         Collections.sort(listOfCountries,new CountrySortByIdComparator());
         
         System.out.println("After Sort by id: ");
         for (int i = 0; i < listOfCountries.size(); i++) {
    Country country=(Country) listOfCountries.get(i);
    System.out.println("Country Id: "+country.getCountryId()+"|| "+"Country name: "+country.getCountryName());
      
   }
 }

}
Output:
Before Sort by id : 
Country Id: 1||Country name: India
Country Id: 4||Country name: China
Country Id: 3||Country name: Nepal
Country Id: 2||Country name: Bhutan
After Sort by id: 
Country Id: 1|| Country name: India
Country Id: 2|| Country name: Bhutan
Country Id: 3|| Country name: Nepal
Country Id: 4|| Country name: China

Anonymous Comparator:

One of advantage of Comparator over comparable is you can create anonymous comparator i.e you don't need to implement Comparable interface to any class.You just need to pass objects to compare method. Lets understand more with help of example:

1.Country.java

package org.arpit.javapostsforlearning;

public class Country{
    int countryId;
    String countryName;
    
    public Country(int countryId, String countryName) {
        super();
        this.countryId = countryId;
        this.countryName = countryName;
    }

    public int getCountryId() {
        return countryId;
    }


    public void setCountryId(int countryId) {
        this.countryId = countryId;
    }


    public String getCountryName() {
        return countryName;
    }


    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }
    
} 

2.ComparatorMain.java

package org.arpit.javapostsforlearning;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComparatorMain {

 /**
  * @author Arpit Mandliya
  */
 public static void main(String[] args) {
  Country indiaCountry=new Country(1, "India");
  Country chinaCountry=new Country(4, "China");
  Country nepalCountry=new Country(3, "Nepal");
  Country bhutanCountry=new Country(2, "Bhutan");

  List<Country> listOfCountries = new ArrayList<Country>();
  listOfCountries.add(indiaCountry);
  listOfCountries.add(chinaCountry);
  listOfCountries.add(nepalCountry);
  listOfCountries.add(bhutanCountry);

  System.out.println("Before Sort by name : ");
  for (int i = 0; i < listOfCountries.size(); i++) {
   Country country=(Country) listOfCountries.get(i);
   System.out.println("Country Id: "+country.getCountryId()+"||"+"Country name: "+country.getCountryName());
  }

  //Sort by countryName
  // Anonymous Comparator
  Collections.sort(listOfCountries,new Comparator<Country>() {

   @Override
   public int compare(Country o1, Country o2) {
    return o1.getCountryName().compareTo(o2.getCountryName());
   }
  });

  System.out.println("After Sort by name: ");
  for (int i = 0; i < listOfCountries.size(); i++) {
   Country country=(Country) listOfCountries.get(i);
   System.out.println("Country Id: "+country.getCountryId()+"|| "+"Country name: "+country.getCountryName());
      
   }
 }

}
Output:
Before Sort by name : 
Country Id: 1||Country name: India
Country Id: 4||Country name: China
Country Id: 3||Country name: Nepal
Country Id: 2||Country name: Bhutan
After Sort by name: 
Country Id: 2|| Country name: Bhutan
Country Id: 4|| Country name: China
Country Id: 1|| Country name: India
Country Id: 3|| Country name: Nepal

So here we have created anonymous Comparator to sort country by name. We have not implemented Comparator to Country class , neither we have created any Comparator specific class.

If subclass is having same method as base class then it is known as method overriding Or in another words, If subclass provides specific implementation to any method which is present in its one of parents classes then it is known as method overriding

Lets start with a real time example:

In a small organization,There are two kinds of Employees i.e. Manager and Developer. Now we want to print salary of employee.


Create class Employee.java in org.arpit.java2blog
Employee.java:
package org.arpit.java2blog;

public class Employee { 
    int employeeId;
    String employeeName;
    double salary;

    public Employee(int employeeId, String employeeName, double salary) {
        super();
        this.employeeId = employeeId;
        this.employeeName = employeeName;
        this.salary = salary;
    }

    public int getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(int employeeId) {
        this.employeeId = employeeId;
    }
    public String getEmployeeName() {
        return employeeName;
    }
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
       this.salary = salary;
    }
}

Manager.java:
package org.arpit.java2blog;

public class Manager extends Employee{

    public static final double BONUSPERCENT=0.2;
    public Manager(int employeeId, String employeeName, double salary) {
        super(employeeId, employeeName, salary);
    }
    public double getSalary() {
        return salary+salary*BONUSPERCENT;
    }
}

Developer.java:
package org.arpit.java2blog;
public class Developer extends Employee{ 
    public static final double BONUSPERCENT=0.1;

    public Developer(int employeeId, String employeeName, double salary) {
        super(employeeId, employeeName, salary);        
    }

    public double getSalary() {

        return salary+salary*BONUSPERCENT;
    }
}

MethodOverridingMain:
package org.arpit.java2blog;

public class MethodOverridingMain {

    /**
     * @author Arpit Mandliya
     */
    public static void main(String[] args) {
        Developer d1=new Developer(1,"Arpit" ,20000);
        Developer d2=new Developer(2,"John" ,15000);
        Manager m1=new Manager(1,"Amit" ,30000);
        Manager m2=new Manager(2,"Ashwin" ,50000);

        System.out.println("Name of Employee:" +d1.getEmployeeName()+"---"+"Salary:"+d1.getSalary());
        System.out.println("Name of Employee:" +d2.getEmployeeName()+"---"+"Salary:"+d2.getSalary());
        System.out.println("Name of Employee:" +m1.getEmployeeName()+"---"+"Salary:"+m1.getSalary());
        System.out.println("Name of Employee:" +m2.getEmployeeName()+"---"+"Salary:"+m2.getSalary());
    }
}

Run it:
When you will run MethodOverridingMain.java.You will get following output:
Name of Employee:Arpit---Salary:22000.0
Name of Employee:John---Salary:16500.0
Name of Employee:Amit---Salary:36000.0
Name of Employee:Ashwin---Salary:60000.0

As you can see here, We are overriding getSalary() method of Employee class in Developer and Manager. Why we need to override getSalary()?
Because we require specific implementation of getSalary() method based on Class. e.g. Developer class and Manager class have different bonus so we need different implementation for both.

Rules for method overriding:

Arguments Must not change
Return type Can't change except for covariant (subtype) returns
Access Modifier Must not be more restrictive. Can be less restrictive.
Exceptions Can reduce or eliminate but must not throw new/broader checked exceptions
ContructorCan not be overriden
Static methodCan not be overriden
final methodCan not be overriden

Now here, I will answer some of the obvious question you could have:

Why can't you make access modifier more restrictive (e.g. public to private)?

It's a fundamental principle in OOP: the child class is a fully-fledged instance of the parent class, and must therefore have at least the same interface as the parent class. Making less visible would violate this idea; you could make child classes unusable as instances of the parent class.
Lets see with the help of example:
class Employee{
 public double getSalary(){
      //some operation
    }
 }


class Developer extends Employee{
   private double id getSalary(){
       //some operation
   }
 } 
Now I could call using :
Employee e1=new Developer();
e1.getSalary();

so even you made getSalary() method of developer private, you will be able to access getSalary() method of developer using reference of Employee(super class) even if you have made it private. so you can't reduce access modifier while overriding method.

Why can't you override static methods?

Because static methods are related to class not to state of object so You can declare static method in child class but it has nothing to do with parent class. It is method hiding not overriding.

Can you override private methods?

No,you can't. A private method cannot be overridden since it is not visible from any other class. You can declare a new method for your subclass that has no relation to the superclass method. So it is not method overriding.

Why can't you override final methods?

Because final methods are meant to be not overridden.You declare a method final because you don't want it to be overridden in subclass.

What if We change number of arguments?

If you change number of arguments then it will be method overloading not overriding. Parent class method and child class method should have same method signature.

What is dynamic binding? 

Binding of overridden methods happen at runtime is known as dynamic binding.

Super keyword:

Super keyword can be used to to call specific parent class method from child class.
For example:
package org.arpit.java2blog;

public class Employee{
 public double getSalary(){
  System.out.println("In Employee class getSalary() method");
  return 0;
 }

 public static void main(String args[])
 {
  Developer d1=new Developer();
  d1.getSalary();
 }
}


class Developer extends Employee{
 public double getSalary(){
               // calling parent class method
  super.getSalary();
  System.out.println("In Developer class getSalary() method");
  return 0;
 }
} 
When you run the program, you will get following output:
In Employee class getSalary() method
In Developer class getSalary() method

 

Java tutorial for beginners Copyright © 2012