In my previous article 5 Different ways to create objects in Java with Example, I have discussed 5 different ways (new keyword, Class.newInstance() method, Constructor.newInstance() method, cloning and serialization-deserialization) a developer can use to create objects, if you haven't read it please go ahead.

Cloning is also a way of creating an object but in general, cloning is not just about creating a new object. Cloning means creating a new object from an already present object and copying all data of a given object to that new object.

In order to create a clone of an object we generally design our class in such a way that
  1. Our class should implement Cloneable interface otherwise, JVM will throw CloneNotSupportedException if we will call clone() on our object.
    Cloneable interface is a marker interface which JVM uses to analyse whether this object is allowed for cloning or not. According to JVM if yourObject instanceof Cloneable then create a copy of the object otherwise throw CloneNotSupportedException.
  2. Our class should have a clone method which should handle CloneNotSupportedException.
    It is not necessary to define our method by the name of clone, we can give it any name we want e.g. createCopy(). Object.clone() method is protected by its definition so practically child classes of Object outside the package of Object class (java.lang) can only access it through inheritance and within itself. So in order to access clone method on objects of our class we will need to define a clone method inside our class and then class Object.clone() from it. For details on protected access specifier, please read Why an outer Java class can’t be private or protected .
  3. And finally, we need to call the clone() method of the superclass, which will call it's super’s clone() and this chain will continue until it will reach to clone() method of the Object class. Object.clone() method is the actual worker who creates the clone of your object and another clone() methods just delegates the call to its parent’s clone().
All the things also become disadvantage of the cloning strategy to copy the object because all of above steps are necessary to make cloning work. But we can choose to not do all above things follow other strategies e.g. Copy Constructors, To know more read Java Cloning - Copy Constructor versus Cloning.
Java Cloning (Shallow Cloning, Deep Cloning)Example

To demonstrate cloning we will create two classes Person and City and override
  1. toString() to show the content of the person object,
  2. equals() and hashCode() method to compare the objects,
  3. clone() to clone the object
However, we are overriding the clone method but it not necessary we can create a clone method by any name but if we are naming it as clone then we will need to follow basic rules of method overriding e.g. method should have same name, arguments and return type (after Java 5 you can also use a covariant type as return type). To know more about method overriding read Everything About Method Overloading Vs Method Overriding.

class Person implements Cloneable {
    private String name; // Will holds address of the String object, instead of object itself
    private int income; // Will hold bit representation of int, which is assigned to it
    private City city; // Will holds address of the City object, instead of City object

    public String getName() {
        return name;
    }
    public void setName(String firstName) {
        this.name = firstName;
    }
    public int getIncome() {
        return income;
    }
    public void setIncome(int income) {
        this.income = income;
    }
    public City getCity() {
        return city;
    }
    public void setCity(City city) {
        this.city = city;
    }

    public Person(String firstName, int income, City city) {
        super();
        this.name = firstName;
        this.income = income;
        this.city = city;
    }

    // But we can also create using any other name
    @Override
    public Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }

    // To print the person object
    @Override
    public String toString() {
        return "Person [name=" + name + ", income=" + income + ", city=" + city + "]";
    }

    // hasCode(), and equals() to compare person objects
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((city == null) ? 0 : city.hashCode());
        result = prime * result + income;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (city == null) {
            if (other.city != null)
                return false;
        } else if (!city.equals(other.city))
            return false;
        if (income != other.income)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

Person class has a reference to City class which looks like below

class City implements Cloneable {
    private String name;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public City(String name) {
        super();
        this.name = name;
    }

    @Override
    public City clone() throws CloneNotSupportedException {
        return (City) super.clone();
    }

    @Override
    public String toString() {
        return "City [name=" + name + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        City other = (City) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

And let's test it

public class CloningExample {

    public static void main(String[] args) throws CloneNotSupportedException {

        City city = new City("Dehradun");
        Person person1 = new Person("Naresh", 10000, city);
        System.out.println(person1);

        Person person2 = person1.clone();
        System.out.println(person2);

        if (person1 == person2) { // Evaluate false, because person1 and person2 holds different objects
            System.out.println("Both person1 and person2 holds same object");
        }

        if (person1.equals(person2)) { // Evaluate true, person1 and person2 are equal and have same content
            System.out.println("But both person1 and person2 are equal and have same content");
        }

        if (person1.getCity() == person2.getCity()) {
            System.out.println("Both person1 and person2 have same city object");
        }
    }
}

person1.clone() calls super.clone() which means Object.clone() method.
Object.clone() method copy content of the object to other object bit-by-bit, means the values of all instance variables from one object will get copied to instance variables of other object.


So (person1 == person2) will evaluate false because person1 and person2 are the copy of each other but both are different objects and holds different heap memory. While person1.equals(person2) evaluate true because both have the same content.

But as we know reference variables holds address of the object instead of object itself, which can also be referred from other reference variables and if we change one other will reflect that change.

So while cloning process Object.clone() will copy address which person1.city is holding to person2.city, So now city, person1.city, and person2.city all are holding the same city object. That’s why (person1.getCity() == person2.getCity()) evaluate true. This behaviour of cloning is known as Shallow Cloning.

Types of Cloning

This behaviour of Object.clone() method classifies cloning into two sections

1. Shallow Cloning

Default cloning strategy provided by Object.clone() which we have seen. The clone() method of object class creates a new instance and copy all fields of the Cloneable object to that new instance (either it is primitive or reference). So in the case of reference types only reference bits get copied to the new instance, therefore, the reference variable of both objects will point to the same object. The example we have seen above is an example of Shallow Cloning.

2. Deep Cloning

As the name suggests deep cloning means cloning everything from one object to another object. To achieve this we will need to trick our clone() method provide our own cloning strategy. We can do it by implementing Cloneable interface and override clone() method in every reference type we have in our object hierarchy and then call super.clone() and these clone() methods in our object’s clone method.

So we can change the clone method of Person class in below way

public Person clone() throws CloneNotSupportedException {
    Person clonedObj = (Person) super.clone();
    clonedObj.city = this.city.clone();
    return clonedObj;
}

Now (person1.getCity() == person2.getCity()) will evaluate false because in clone() method of Person class we are clonning city object and assigning it to the new clonned person object.

In below example we have deep copied city object by implementing clone() in City class and calling that clone() method of person class, That's why person1.getCity() == person2.getCity() evaluate false because both are separate objects. But we have not done same with Country class and person1.getCountry() == person2.getCountry() evaluate true.

public class CloningExample {

    public static void main(String[] args) throws CloneNotSupportedException {

        City city = new City("Dehradun");
        Country country = new Country("India");
        Person person1 = new Person("Naresh", 10000, city, country);
        System.out.println(person1);

        Person person2 = person1.clone();
        System.out.println(person2);

        // Evaluate false, because person1 and person2 holds different objects
        if (person1 == person2) {
            System.out.println("Both person1 and person2 holds same object");
        }

        // Evaluate true, person1 and person2 are equal and have same content
        if (person1.equals(person2)) {
            System.out.println("But both person1 and person2 are equal and have same content");
        }

        // Evaluate false
        if (person1.getCity() == person2.getCity()) {
            System.out.println("Both person1 and person2 have same city object");
        }

        // Evaluate true, because we have not implemented clone in Country class
        if (person1.getCountry() == person2.getCountry()) {
            System.out.println("Both person1 and person2 have same country object");
        }

        // Now lets change city and country object and print person1 and person2
        city.setName("Pune");
        country.setName("IN");

        // person1 will print new Pune city
        System.out.println(person1);
        // while person2 will still print Dehradun city because person2.city holds a separate city object
        System.out.println(person2);
    }
}

class Person implements Cloneable {
    private String name; // Will holds address of the String object which lives
                         // in SCP, instead of String object itself
    private int income; // Will hold bit representation of int, which is assigned to it
    private City city; // Will holds address of the City object which lives in
                        // heap, instead of City object
    private Country country;

    public String getName() {
        return name;
    }

    public void setName(String firstName) {
        this.name = firstName;
    }

    public int getIncome() {
        return income;
    }

    public void setIncome(int income) {
        this.income = income;
    }

    public City getCity() {
        return city;
    }

    public void setCity(City city) {
        this.city = city;
    }

    public Country getCountry() {
        return country;
    }

    public void setCountry(Country country) {
        this.country = country;
    }

    public Person(String name, int income, City city, Country country) {
        super();
        this.name = name;
        this.income = income;
        this.city = city;
        this.country = country;
    }

    @Override
    public Person clone() throws CloneNotSupportedException {
        Person clonedObj = (Person) super.clone();
        clonedObj.city = this.city.clone();
        return clonedObj;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", income=" + income + ", city=" + city + ", country=" + country + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((city == null) ? 0 : city.hashCode());
        result = prime * result + ((country == null) ? 0 : country.hashCode());
        result = prime * result + income;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (city == null) {
            if (other.city != null)
                return false;
        } else if (!city.equals(other.city))
            return false;
        if (country == null) {
            if (other.country != null)
                return false;
        } else if (!country.equals(other.country))
            return false;
        if (income != other.income)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

class City implements Cloneable {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public City(String name) {
        super();
        this.name = name;
    }

    public City clone() throws CloneNotSupportedException {
        return (City) super.clone();
    }

    @Override
    public String toString() {
        return "City [name=" + name + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        City other = (City) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

class Country {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Country(String name) {
        super();
        this.name = name;
    }

    @Override
    public String toString() {
        return "Country [name=" + name + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Country other = (Country) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

Java cloning is not considered a good way to copy an object and lots of other ways are there to do the same. You can read Java Cloning - Copy Constructor versus Cloning to get more knowledge on why Java cloning is not a preferred way of cloning and what are other ways to overcome this.
In a previous blog, I talked about why we can not define an outer class using private or protected keywords. If you have not read it, please go ahead and give it a look.

In this article I will talk what is the use of the static keyword, why an outer Java class can’t be static, why it is not allowed in Java to define a static outer class. In order to understand that first, we need to understand what is the static keyword used for, what purpose it solves and how does it work.

What does static keyword do

Every Java programmer knows that if we need to define some behaviour (method) or state (field) which will be common to all objects we define it as static. Because static content (behaviour or state) does not belong to any particular instance or object, it will common to all objects and all objects are free to change any static field and every change will be visible to every object.

We do not need to create an object of the class to access a static field or method, we can directly refer a static field or method by using class name and dot operator e.g. Class.forName(“ClassName”).
This happens because JVM creates a Class level object for every class when Classloader loads the class into memory. And all static content of that class belongs this Class object and all other objects of that class refer to this class level object for all static content. A class-level object is actually an object of java.lang.Class and it is referred by your_class_name.class syntax.

For Example for the below statement, two objects will get created

Employee emp =  new Employee();

One is ‘emp’ (the new Employee();) itself and another one is the ‘class level object’ of Employee class which will get created while JVM will load Employee class into memory and we can refer it by Employee.class. And this class level object holds all the static content of the Employee class either it is a variable or method. If we are accessing any static content through emp object it automatically points to Employee.class object to access that.

That is the reason why a static variable got changed for every object even if we change it for a single emp object because all emp objects are pointing same copy of that variable from Employee.class object, for more information read Why Java is Purely Object-Oriented Language Or Why Not.

Why an outer Java class can’t be static

From above we can conclude that we should define members as static which
  1. Should be common to all objects of the class.
  2. Should belong to the class and accessible by class name.
  3. Should not need an object of the class to access them.
Now suppose we are defining an outer class as static and suppose we are allowed to do so. Will this serve any purpose or provide any advantage to a developer or it will create ambiguity and complications for both developers and language creators?

Let’s check, defining an outer class as static will serve purposes which we have defined above or not?
  1. Every class is already common to all of its objects and there is no need to make it static to become available to all of its objects.
  2. We need a class name to access its static members because these members are part of class while an outer class is part of the package and we can directly access the class by just writing package_name.class_name (similar to class_name.static_field_name), So again there is no need to do which is already there by default.
  3. We do not need any object to access a class if it is visible, we can simply write package_name.class_name to access it. And by definition, a class is a blueprint for its objects and we create a class to create objects from it (exception will always be there e.g. java.lang.Math), again there is no need to define an outer class as static.
From the above points, we can say Java creators had not allowed an outer class to be static because there is no need to make it static. Allowing to make the outer class static will only increase complications, ambiguity and duplicity.

You can find the complete source code for this article on this Github Repository and please feel free to provide your valuable feedback.
As soon as we try to use private or protected keyword while declaring an outer class compiler gives a compilation error saying “Illegal modifier for the class your_class_name; only public, abstract & final are permitted”.

Here in this article, we are going to study why we are not allowed to use these keywords while declaring outer classes. But before understating the reason behind this we need to understand Java access specifiers and their use cases. There is total 4 access specifier in Java mentioned below in the order of their accessibility.

  1. private: anything (field, class, method, interface etc.) defined using private keyword is only accessible inside the entity (class or package or interface) in which it is defined. 
  2. default: only accessible inside the same package and it is also known as package-private (No modifiers needed).
  3. protected: only accessible inside the same package plus outside the package within child classes through inheritance only. 
  4. public: can be accessed from anywhere.

Why an outer class can not be private

As we already know a field defined in a class using private keyword can only be accessible within the same class and is not visible to outside world.

So what will happen if we will define a class private, that class will only be accessible within the entity in which it is defined which in our case is its package?

Let’s consider below example of class A

package com.example;
class A {
    private int a = 10;

    // We can access a private field by creating object of same class inside the same class
    // But realy no body creates object of a class inside the same class
    public void usePrivateField(){
        A objA =  new A();
        System.out.println(objA.a);
    }
}

Field ‘a’ is declared as private inside ‘A’ class and because of it ‘a’ field becomes private to class ‘A' and can only be accessed within ‘A’. Now let’s assume we are allowed to declare class ‘A’ as private, so in this case class ‘A’ will become private to package ‘com.example’ and will not be accessible from outside of the package.

So defining private access to the class will make it accessible inside the same package which default keyword already do for us, Therefore there is no benefit of defining a class private it will only make things ambiguous.

Why an outer class can not be protected

Access specifier protected is sometimes got confused with the default keyword, for some programmers it becomes hard to identify the exact difference between default and protected accesses. But it is very clear as mentioned below

    default → only accessible within the same package.
    protected → accessible within the same package as well as outside of the package in child classes  through inheritance only.

Let’s consider below example of class A

package com.example;
public class A {
    protected int a = 10;
}

And suppose there is one more class in another package

package com.experiment;
public class B extends A {

    // Outside of the package protected field can be accessed through inheritance
    public void printUsingInheritance() {
        System.out.println(a);
    }

    // In child class we can access protected field through instantiation of child class
    // But should we do that ? .... No
    public void printUsingInstantiation() {
        B b = new B();
        System.out.println(b.a);

        // But not through instantiation of the class which contains the protected field
        A a = new A();
        System.out.println(a.a); // Compilation error “The field A.a is not visible”
    }
}

And suppose there is one more class in the same package

package com.experiment;
public class C {

    // We can not access protected field outside of the child class through instantiation
    public void printUsingInstantiation() {
        B b = new B();
        System.out.println(b.a); // Compilation error “The field B.a is not visible”
    }
}

And if same class 'C' extends 'B', Then again we will be able to access 'a' the same way we are able to access it in B class

package com.experiment;
public class C extends B {

    // outside of the package protected field can only be accessed through inheritance
    public void printUsingInheritance() {
        System.out.println(a);
    }

    // In child class we can access protected field through instantiation as well
    public void printUsingInstantiation() { 
        C c = new C();
        System.out.println(c.a);
    }
}

Because ‘a’ field is protected, we can access it in any way we want to inside the package but outside of the package ‘com.example’ it is only accessible through inheritance and because class ‘B’ is extending class ‘A’ we can use field ‘a’ inside class ‘B’ only as we are doing in printUsingInheritance() method. And we can not use ‘a’ outside of class ‘B’ without inheriting 'B' in another class.

Field ‘a’ will be accessible inside class B in through inheritance only but if we try to create an instance of class ‘B’ in ‘B’ class and then try to access ‘a’ from that instance we will able to use it in a similar manner we can use a private variable in the same class by instantiation of same class.

So If we are allowed to make a class protected then we can access it inside the package very easily but for accessing that class outside of the package we first need to extend that entity in which this class is defined which is again is its package.

And since a package can not be extended (can be imported) defining a class protected will again make it similar to defining it as default which we can already do. So again there is no benefit of defining a class protected.

Please feel free to reach me if you face any problem in understanding it or found any problem in the article.
Complete explanation of Object Oriented JavaScript

01:50 JavaScript Objects
02:36 Objects in Objects
04:12 Constructor Functions
05:58 instanceof
06:28 Passing Objects to Functions
08:09 Prototypes
09:34 Adding Properties to Objects
10:44 List Properties in Objects
11:38 hasOwnProperty
12:42 Add Properties to Built in Objects
14:31 Private Properties
18:01 Getters / Setters
21:20 defineGetter / defineSetter
24:38 defineProperty
27:07 Constructor Function Getters / Setters
29:40 Inheritance
37:13 Intermediate Function Inheritance
39:14 Call Parent Functions
41:51 ECMAScript 6
47:31 Singleton Pattern
49:32 Factory Pattern
52:53 Decorator Pattern
54:52 Observer Pattern



Some years back when I was learning Java, I got to know that Java follows Object Oriented Programming paradigm and everything in Java is an object either it is a String (which was a char array in C) or an array itself.

But later on I found on the internet, people are saying that Java is actually not a purely object-oriented because everything in Java is not an object, for example:
  1. All primitive types (char, boolean, byte, short, int, long, float, double) are not objects because we can not perform any object related operation (using . and calling methods) on them.
  2. I have seen some people some saying that all the static content (variables and methods) does not belong to any object so they are non-object things.
I easily accepted these reasons and started to believe that Java is not a pure object-oriented programming language.

But later on, I found that for every object JVM creates two objects
  1. The object itself.
  2. And one Class level object which gets created only once when classloader loads the class into memory. And all static content of that class belongs to this Class object and all other objects of that class refer to this class level object for all static content.
For Example for below statement, there will be two objects

Employee emp = new Employee();

One is emp itself and another one is the class level object of employee class. If we are accessing any static content through the emp object it points to the class level object to access that.

That's the reason why static variables get changed for every object even if we change it for a single emp object because all objects are pointing to the same copy of that variable from class level object.

Now 2nd point got canceled because the static content does belong to an object. But the 1st point is still there and we still have primitive data types which are not objects in Java. However wrapper classes are there and due to autoboxing (automatic unboxing-boxing, boxing-unboxing), we can directly assign a primitive literal to its Wrapper class reference.

But still, we can’t perform object related operations on primitives variables we always need to create objects of the respective wrapper class, for example

Integer obj = new Integer(5); // here we can do obj.toString()
int i = 5; // but we can't do i.toString() here

And due to these reasons, we say primitive types are not objects but what if that’s actually an elusion and it is end-user perspective (Java developers are end user to Java because we are using it not creating it).

If we dig down deep into the Java source codes we can find that JVM internally treats all primitive types as objects and proof of this can be found in source code or Javadoc of class Class, according to source code class Class

Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects

And Javadoc code of Class.isPrimitive() method says

public boolean isPrimitive()
Determines if the specified Class object represents a primitive type.
There are nine predefined Class objects to represent the eight primitive types and void. These are created by the Java Virtual Machine, and have the same names as the primitive types that they represent, namely boolean,byte, char, short, int, long, float, and double.
These objects may only be accessed via the following public static final variables, and are the only Class objects for which this method returns true.
Returns:
true if and only if this class represents a primitive type
Since:
JDK1.1
See Also:
Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE

If we open source code of class Class and do a CTRL + F for "primitive” word we will find lots of reason to believe that JVM treats all primitive types as objects internally.

Also if we open source of the Integer class search for Integer.TYPE entry, we will find

public static final Class[Integer](https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html) TYPE
The Class instance representing the primitive type int.

And if we write below the line in your program in eclipse

Integer.TYPE i = 5;

We get a compilation error saying Integer.TYPE cannot be resolved to a type with a hint from eclipse to change it to int.

So if all primitive types are objects for JVM then why should we use primitive types

primitive-type-and-wrapper-classes-in-java

If JVM creates objects for all primitive types then why do we need to use primitive types instead of creating an object of its respective wrapper classes. That’s because JVM creates these native objects for primitive types internally and those objects are very lightweight and optimized than their respective wrapper class objects and due to this, they have less functionality e.g. we can’t call methods on them because they don’t have any.

We should use primitive types because:
  1. They are fast e.g. below program takes 9 seconds to run on my machine while it takes 0 seconds if I convert Long sum to long sum.
     public static void main(String[] args) {
 long millis = System.currentTimeMillis();
 Long sum = 0L; // uses Long, not long
 for (long i = 0; i <= Integer.MAX_VALUE; i++) {
  sum += i;
 }                     

 System.out.println(sum);

 System.out.println((System.currentTimeMillis() - millis) / 1000);
  1. They allow us to use native equality operator ==
     new Integer(3) == new Integer(3); // false
     new Integer(100) == new Integer(100); // false
     Integer.valueOf(5) == Integer.valueOf(5); //true
     Integer.valueOf(100) == Integer.valueOf(100); //false

4th statement gives false because the 256 integers closest to zero [-128; 127] are cached by the JVM, so they return the same object for those. Beyond that range, they aren't cached, so a new object is created.

So there are enough reasons to say JVM treats all primitive types as objects internally, however, we can’t use them in that way and we have got Wrapper classes for that.

This is why Java is purely Object Oriented Language, Please mention in comments what do you think Java is a purely Object Oriented Language or not.
Java 8 is one of most popular release in the history of Java and have introduced lots of major features like Lambda Expression, Method Reference, Stream API, new DateTime API, Default and static interface methods etc.. For complete list of new Java 8 feature read What’s New in JDK 8 article by oracle itself.

In this article, we are going to study Java Lambda Expression in details e.g. what is the lambda expression, why it so popular, what are the advantages of the lambda expression, what purpose is solved, how it differs from anonymous classes and why/how should we use it.
lambda expression logo

Why Java needs Lambda Expression

Java is a multiparadigm programming language (Supports Object Oriented, Imperative, Structured, Declarative style of programming). However, most of its design architecture is influenced by Object Oriented programming style.

And there are two variations of object-oriented programming (OOP) style
  • Class-based OOP style
  • Prototype-based OOP style → doesn’t support inheritance
Java supports class-based OOP style that’s why there should be a class for every object while JavaScript follows Prototype-based OOP style that’s why we don’t have the concept of class and inheritance in JavaScript. Everything in JavaScript is an object either it is a variable or a function while in Java a function (method) is state of the object.

Apart from this JavaScript also follows the Functional style of programming so we can assign functions to variables, pass functions as argument or return a function from other function etc..

Due to class-based nature of Java programming, it is hard to maintain functions as first class citizen similar as objects. That’s why Java does not support functional style of programming (before Java 8) and we can’t assign functions to variables or pass functions as argument or return them.

Lambda Expression is a way to introduce functional programming to Java. So by using lambda expression we can simply define and use functions wherever we need them (e.g. inside a method) without even creating objects. Due to lambda expression now functions have also become first class citizens in Java language.

What is Lambda Expression

By definition

A Lambda Expression is an anonymous function (a function defined, and possibly called, without being bound to an identifier and a name.

The concept is similar to anonymous classes or anonymous objects, Now we can declare methods wherever we want them without any name. The sole purpose of writing an anonymous class object is to override its method and provide our own functionality but for that single method, we always need to declare the class. With lambda expression, we can eliminate the declaration of the anonymous class and we can simply write the methods.

Since the old days of Swing, we always had written anonymous classes if we wanted to pass some functionality to any method. For example old event listener code and thread creation code look like

Runnable runnable = new Runnable() {
  @Override
  public void run() {
  System.out.println("Running thread using anonymous class");
  }
};
Thread thread = new Thread(runnable);

If you look at above code the actual functionality of the thread is written in the run() method. And we are creating an anonymous class object just to define a single method which is really unnecessary if we can do functional programming (just create the function where it needs). So here the creation of anonymous class Can be replaced by lambda as below which is just a single line of code:

Runnable runnable = () -> System.out.println("Running thread using lambda expression");
Thread thread = new Thread(runnable);

Above we have assigned a lambda to the reference variable but more precisely we create a thread as below if r is not reusable.

Thread t = new Thread(() -> System.out.println("Running thread using lambda expression"));

How to write Lambda Expression

Through lambda expression, we can write functional code but this is still not similar to other functional programming languages like C, C++, JavaScript.

Java is still a class based object oriented language and methods always belong to some class, abstract class or interface. So methods implemented using lambda expression must have to define somewhere. So along with Lambda Expression Oracle engineers have applied some tweaks and introduced the concept of Functional Interfaces.

Functional Interface → An interface with only one abstract method and optionally annotated with @FunctionalInterface annotation.

We can use lambda expressions only with Functional interfaces, in above example the Runnable interface is a functional interface.
Lambda expressions in Java is usual written using syntax (argument) -> (body)

lambda expression syntax

Converting anonymous classes to Lambda Expression

After little bit practice, you will not feel any need for conversion, you will start writing lambdas without any confusion. But whenever you got confused conversion approach is the best way to create lambdas.

We can convert the old anonymous class code to lambda expression as below, suppose we want to create lambda expression for thread generation process:

Runnable runnable = new Runnable() {
  @Override
  public void run() {
  System.out.println("In thread");
  System.out.println("doing something");
  }
};

Remove below things in order
→ new keyword new,
→ class name and it’s parentheses Runnable(),
→ class opening and closing braces { };,
@Override annotation (if have any),
→ remove method declaration (leave argument parentheses ()) public void run
→ removing method opening { and closing braces } is not necessary, however, if you have single line of code in it then you can remove them
→ add -> between parentheses () and execution code inside { }

Runnable runnable = new Runnable() {
  @Override
  public void run() -> {
  System.out.println("In thread");
  System.out.println("doing something");
  }
};

So now our lambda expression will become

Runnable runnable = () -> {
  System.out.println("In thread");
  System.out.println("doing something");
}


Single line Zero Argument method: If we have a single line of code inside execution block {} then we can remove them.

Runnable r = () -> System.out.println("In thread");

Multiple Argument Methods: If functional interface’s method definition have arguments then we can write them inside ()

Comparator<Integer> comparator = (Integer i, Integer j) -> i.compareTo(j);

Single Argument Methods: And if there is only one argument then we can eliminate () braces
Consumer<String> consumer = obj -> System.out.println(obj);

Difference between Lambda Expression and Anonymous class

  • An anonymous class object creates a separate class file after compilation which increases the size jar while after compilation Lambda expression becomes invokedynamic which dynamic language implementation.
  • We can use this keyword to represent the current class in lambda expression while in the case of anonymous class this keyword represents that particular anonymous class.
  • In the case of Lambda expression, we need to provide the function body only while in the case of anonymous class we need to write the redundant class definition.

Advantages of Lambda Expression

Lambda Expressions allows us to code in functional style so it provides all benefits of functional style as well as above we can see Lambda Expressions lets developers
  • Simply understand the code.
  • Simplify and shorten their code.
  • Making it more readable and maintainable.
  • Remove more verbose class declarations.

Examples of Lambda Expressions

In below program, I have demonstrated different examples you can also found the source code on Github.

package org.programming.mitra.exercises;

import java.awt.Button;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.stream.IntStream;

public class LambdaExpression {

  @SuppressWarnings("unused")
  public static void main(String[] args) {

  // Example : Thread Creation
  // Old Way
  Runnable runnable = new Runnable() {
  @Override
  public void run() {
  System.out.println("Running thread using anonymous class");
  }
  };
  Thread thread = new Thread(runnable);
  thread.start();

  // New Way
  runnable = () -> System.out.println("Running thread using lambda expression");
  thread = new Thread(runnable);
  thread.start();

  // Example : Comparator Creation
  Comparator<Integer> comparator = (Integer i, Integer j) -> i.compareTo(j);

  // Example : Consumer Creation
  Consumer<String> consumer = obj -> System.out.println(obj);

  // Example : Consumer Creation
  Button button = new Button();

  // Old way:
  button.addActionListener(new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
  System.out.println("button clicked");
  }
  });

  // New way:
  button.addActionListener((e) -> {
  System.out.println("button clicked");
  });

  // Example : Iteration
  System.out.println("####### Old way #######");
  for (int i = 1; i < 10; i++) {
  int j = i * i;
  System.out.println(j);
  }

  System.out.println("####### Lambda (Stream) way #######");
  IntStream.range(1, 10)
  .map(num -> num * num)
  .forEach(i -> System.out.println(i));

  }
}

Lambda expressions are heavily used in Java Stream API, which I am going to cover in later articles.
Whenever we install Java using JDK installer it creates two folders in installation directory one for JDK and one for JRE. However, JDK folder also contains one JRE folder itself and both have the same directory structure.

JDK Structure
JDK Structure

Let’s assume JDK is installed at \jdk1.7.0, below are some of the most important directories and their explanation
jdk1.7.0
    db
    include
    src.zip
    bin
         java*
         javac*
         javap*
         javah*
         javadoc*
    lib
         tools.jar
         dt.jar
    jre
         bin
              java*
         lib
              applet
              ext
                   jfxrt.jar
                   localdata.jar
              fonts
              security
              sparc
                   server
                   client
              rt.jar
              Charsets.jar


\jdk1.7.0 → This is the root directory of the JDK software installation which contains copyright, license, and readme files, src.zip and all other directories.


\jdk1.7.0\bin → Contains files for all executable tools which are necessary for Java program development . The PATH environment variable should contain an entry for this directory. Some of them are
  • appletviewer: Run and debug applets without a web browser.
  • extcheck: Utility to detect Jar conflicts.
  • jar: Create and manage Java Archive (JAR) files.
  • java: The launcher for Java applications.
  • javac: The compiler for the Java programming language.
  • javadoc: API documentation generator.
  • javah: C header and stub generator. Used to write native methods.
  • javap: Class file disassembler
  • jdb: The Java Debugger.


For more information on the tools, see the JDK Tools.


\jdk1.7.0\lib → Files used by the development tools, includes the following:
  • tools.jar: Contains non-core classes for support of the tools and utilities in the JDK.
  • dt.jar: DesignTime archive of BeanInfo files that tell interactive development environments (IDEs) how to display the Java components and how to let the developer customize them for an application.
  • ant-javafx.jar: Contains Ant tasks for packaging JavaFX applications; see Packaging in Deploying JavaFX Applications.
Other jars are jconsole.jar, packager.jar, sa-jdi.jar.


\jdk1.7.0\jre → Root directory of the Java runtime environment used by the JDK development tools. The runtime environment is an implementation of the Java platform. This is the directory represented by the java.home system property.


\jdk1.7.0\jre\bin → Contains executable files and DLLs for tools and libraries used by the Java platform. The executable files are identical to files in /jdk1.7.0/bin. The java launcher tool serves as an application launcher (and replaced the old jre tool that shipped with 1.1 versions of the JDK). This directory does not need to be in the PATH environment variable.


\jdk1.7.0\jre\bin\client → Contains the DLL files used by the Java HotSpot™ Client Virtual Machine.


\jdk1.7.0\jre\bin\server → Contains the DLL files used by the Java HotSpot™ Server Virtual Machine.


\jdk1.7.0\jre\lib → Code libraries, property settings, and resource files used by the Java runtime environment. For example:
  • rt.jar: Contains all Java platform's core API classes. These classes are loaded by Bootstrap Classloader.
  • charsets.jar: Character conversion classes
  • jfxrt.jar: JavaFX runtime libraries
Aside from the ext subdirectory (described below), there are several additional resource subdirectories not described here.


\jdk1.7.0\jre\lib\ext → Default installation directory for Extensions to the Java platform, Loaded by extension classloader.
  • localedata.jar: locale data for java.text and java.util.


\jdk1.7.0\jre\lib\security → Contains files used for security management. These include the security policy (java.policy) and security properties (java.security) files.


\jdk1.7.0\jre\lib\applet → Jar files containing support classes for applets can be placed in the lib/applet/ directory. This reduces startup time for large applets by allowing applet classes to be pre-loaded from the local file system by the applet class loader, providing the same protections as if they had been downloaded over the net.


\jdk1.7.0\jre\lib\fonts Contains TrueType font files for use by the platform.

There are some additional files and directories which are not required to a Java developer like below



\jdk1.7.0\src.zip → Archive containing source code for the Java platform.
\jdk1.7.0\db → Contains Java DB.
\jdk1.7.0\include → C language header files that support native-code programming using the Java Native Interface and the Java Virtual Machine Debugger Interface.

Reference: Java Documentation
Next Post Newer Posts Previous Post Older Posts Home