How many Ways to Create an Object in Java
There are five different ways to create an object in Java:
1) Java new Operator
This is the most popular way to create an object in Java. A new operator is also followed by a call to constructor which initializes the new object. While we create an object it occupies space in the heap.
Example of Java new Operator
2) Java Class.newInstance() method
Java Class.newInstance() is the method of Class class. The Class class belongs to java.lang package. It creates a new instance of the class represented by this Class object. It returns the newly created instance of the class.
It throws IllegalAccessException if the class or its nullary constructor is not accessible. It also throws InstantiationException, if the Class represents an abstract class, an interface, an array class, or a primitive type.
3) Java newInstance() method of Constructor class
Java Constructor class also has a newInstance() method similar to newInstance() method of Class class. The newInstance() method belongs to java.lang.reflect.Constructor class. Both newInstance() method are known as reflective ways to create object. In fact the newInstance() method of Class class internally uses newInstance() method of Constructor class. The method returns a new object created by calling the constructor.
The newInstance() method throws the following Exception:
4) Java Object.clone() method
Java clone() method creates a copy of an existing object. It is defined in Object class. It returns clone of this instance. The two most important point about clone() method is:
When we use clone() method in class, the class must call super.clone() to obtain the cloned object reference.
The method throws the CloneNotSupportedException if the Object class does not support the Cloneable interface. This exception also throws when subclass that overrides the clone() method indicates that instance cannot be cloned.
5) Java Object Serialization and Deserialization
A class must implement Serializable interface which belongs to java.io package. The Serializable interface does not have any method and field. They add special behavior to the class. Marker interface does not used in Java 8. It is replace by Annotations.
JVM creates a separate space whenever we serialize and deserialize an object. It does not use any constructor to create an object.
The ObjectOutputStream class is used to serialize an object. The Serialization is a process of converting an object into a sequence of bytes.
The writeObject() method of ObjectOutputStream class serialize an object and write the specified object to the ObjectOutputStram class. The signature of the method is:
The method accepts an object as a parameter.
The process of creating an object from sequence of bytes is called object deserialization. The readObject() method of ObjectInputStream class read an object from the ObjectInputStram class and deserialize it. The signature of the method is:
The method does not accept any parameter. It returns an object read from the stream. The method throws the following exceptions:
In the following example we have first serialized the object and then deserialized the object.
Concept of cloning in Java
In OOPs, copying an object means creating a clone of an existing object. There are many ways to copy an object; two of them are- copy constructor and cloning. There are two types of cloning in Java:
Both deep and shallow copy are types of object cloning. When we talk about an object, we consider it as a single unit which cannot be broken down further.
Suppose we have a Student object. The Student object contains other objects, as in the following figure. The Student object contains Name and Address objects. The Name contains FirstName and LastName objects, and the Address object is composed of a Street and a city object. When we talk about Student, we are talking about the entire network of objects.
A clone of an object is created when we want to modify or move an object while still preserving the original object.
For example, if we want to create a shallow copy of the Student, we should create a second object of Student. But both objects share the same Name and Address. Consider the following Example:
A disadvantage of the shallow copy is that the two objects are not independent. When we modify the Name object of one Student, it modifies the other Students objects too.
In the following example, we have a Student object with a reference variable mba; then we make a copy of MBA, creating a second Student object, mca. If mca tries to moveOut() by modifying his Address object, the mba moves with it.
It is because mba and mca objects shares the same Address object. If we change the Address in one object, it modifies both.
When we modify the Address object of one Student object, it does not modify the other Student object. In the following code we can see that we are not only using a copy constructor on Student object, but we are also using copy constructor on the inner objects as well.
To create a deep clone, we need to keep copying all the Student object nested elements, until there are only primitive types and Immutable left.
The Street object has two instance variable name and number. The number is a primitive integer value, not an object. It cannot be shared. When we create a second instance variable, we are automatically creating an independent copy. In the above code String is an immutable object i.e., once created, can never be changed again. Hence, we can share it without creating a deep copy of it.