Class Object in Java
Say our trainer has asked for a single pager resume. The trainer also has given a set of things in a document(Like -name, technology, experience, contact number, etc).In the real-world, this document is treated as a template or blueprint and each individual when created their resume follows the same rules with different data. In this example, we can say the class is a template of the document and each document created from this template is called an object. The objects will have their own set of data.
The Object class is the root of all classes available in Java. The Object class is the ultimate superclass of all other classes in Java. Because every other class is a subclass of Object,
all of the methods accessible from Object are inherited by every other class. In other words, all objects in Java, including arrays, have access to implementations of the methods in Object.
So it is the parent in the hierarchy. Every class has an Object as a superclass(parent). All objects implement methods of this class. All objects can invoke the public and protected methods of this class.
So, in general, the flow of the class and object creation is something like:
define a class->create objects form the class->send message to the objects
The methods of Object provide some basic object functionality.
equals() tests whether two objects have the same value (i.e., not whether two variables refer to the same object, but whether two distinct objects have byte-for-byte equivalence).
The hashCode() method returns a hashcode for an object.
For classes that implement the Cloneable interface, clone() makes a byte-for-byte copy of an Object.
getClass() returns the Class object associated with any Object, and the notify(), notifyAll(), and wait() methods are used for thread synchronization on a given Object.
A number of these Object methods should be overridden by subclasses of Object. Subclasses should provide their definition of the toString() method so that they can be used with the string concatenation operator and with the PrintWriter.println() methods. Defining the toString() method for all objects also helps with debugging.
Classes that contain references to other objects may want to override the equals() and clone() methods (for Cloneable objects) so that they recursively call the equals() and clone() methods of the objects referred to within the original object. Some classes, particularly those that override equals(), may also want to override the hashCode() method to provide an appropriate hashcode to be used when storing instances in a Hashtable data structure.
Classes that allocate system resources other than memory (such as file descriptors or windowing system graphic contexts) should override the finalize() method to release these resources when the object is no longer referred to and is about to be garbage collected.
Although it is possible to create an instance of the Object class, this is rarely done because it is more useful to create specialized objects. However, it is often useful to declare a variable that contains a reference to an Object because such a variable can contain a reference to an object of any other class.
Aristotle was first to begin a study of the concept of type. He spoke about “the class of fishes and the class birds”.The concept that all objects while being unique, are also part of the set of objects that have characteristics and behaviors in common was directly used in the first object-oriented language(Simula-67).
Its fundamental keyword class that introduces a new type into a program(class and type are often used synonymously).
A class is describing “a class of objects”.If we create a class of birds, any object belonging t this class will share these characteristics and behaviors.
The structure of the original Object class is as follows:
public class java.lang.Object{
//Conctuctor
public Object();
// creates a new instance of the Class Object and allocates memory for it.
/Methods:
protected native Object clone() throws CloneNotSupportedException;
protected void finalize() throws Throwable;
public boolean equals(Object obj);
public final native Class getClass();
public native int hasCode();
public final native void notify();
public final native void notifyAll();
public String toString();
public final void wait()throws InterruptedException;;
public final native void wait(long timeOut)throws InterruptedException;
public final void wait(long timeOut,int nanos)throws InterruptedException;
}
The details of the class structure are given as follows:
public Object();
public Object() constructor creates an instance of the Object class.
public boolean equals(Object obj);
public boolean equals(Object obj) method returns true if the obj parameter refers to the same object as the object this method is associated with. This is equivalent to using the == operator to compare two objects.
Some classes, such as String, override the equals() method to provide a comparison based on the contents of the two objects, rather than on the strict equality of the references. Any subclass can override the equals() method to implement an appropriate comparison, as long as the overriding method satisfies the following rules for an equivalence relation:
- The method is reflexive : given a reference x, x.equals(x) returns true.
- The method is symmetric: given references x and y, x.equals(y) returns true if and only if
y.equals(x) returns true. - The method is transitive: given references x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) returns true.
- The method is consistent: given references x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided that no information contained by the objects referenced by x or y changes.
- A comparison with null returns false: given a reference x that is non-null, x.equals(null) returns false.
This method returns true if the objects are equal; false if they are not.
Parameter
obj – The object to be compared with this object.
public final native Class getClass();
public final native Class getClass() method returns the Class object that describes the class of this object. This method is final, so it cannot be overridden by subclasses.
This method returns a reference to the Class object that describes the class of this object.
public native int hashCode();
public native int hashCode() method calculates a hashcode value for this object. The method returns an integer value that should be relatively unique to the object. If the equals() method for the object bases its result on the contents of the object, the hashcode() method should also base its result on the contents.
The hashCode() method is provided for the benefit of hashtables, which store and retrieve elements using key values called hashcodes. The internal placement of a particular piece of data is determined by its hashcode; hashtables are designed to use hashcodes to provide efficient retrieval.
The java.util.Hashtable class provides an implementation of a hashtable that stores values of type Object. Each object is stored in the hashtable based on the hash code of its key objectives. Each object must have the most unique hash code possible. If two objects have the same hash code but they are not equal (as determined by equals()), a Hashtable that stores these two objects may need to spend additional time searching when it is trying to retrieve objects.
The implementation of hashCode() in Object tries to make sure that every object has a
distinct hash code by basing its result on the internal representation of a reference to the object.
Some classes, such as String, override the hashCode() method to produce values based on the contents of individual objects, instead of the objects themselves. In other words, two String objects that contain the same strings have the same hash code. If String did not override the hashCode() method inherited from Object, these two String objects would have different hash code values and it would be impossible to use String objects as keys for hashtables.
Any subclass can override the hashCode() method to implement an appropriate way of producing hash code values, as long as the overriding method satisfies the following rules:
- If the hashCode() method is called on the same object more than once during the execution of a Java application, it must consistently return the same integer value. The integer does not, however, need to be consistent between Java applications, or from one execution of an application to another execution of the same application.
- If two objects compare as equal according to their equals() methods, calls to the hashCode() methods for the objects must produce the same result.
- If two objects compare as not equal according to their equals() methods, calls to the hashCode() methods for the two objects are not required to produce distinct results. However, implementations of hashCode() that produce distinct results for unequal objects may improve the performance of hashtables.
In general, if a subclass overrides the equals() method of Object, it should also override the hashCode() method.
This method returns a relatively unique value that should be the same for all objects that are considered equal.
public final native void notify();
public final native void notifies () method wakes up a thread that is waiting to return from a call to this object’s wait() method. The awakened thread can resume executing as soon as it regains this object’s lock. If more than one thread is waiting, the notify() method arbitrarily awakens just one of the threads.
The notify() method can be called only by a thread that is the current owner of this object’s lock. A thread holds the lock on this object while it is executing a synchronized instance method of the object or executing the body of a synchronized statement that synchronizes on the object.
A thread can also hold the lock for a Class object if it is executing a synchronized static method of that class. This method is final, so it cannot be overridden by subclasses.
public final native void notifyAll();
public final native void notifyAll() method wakes up all the threads that are waiting to return from a call to this object’s wait() method. Each awakened thread can resume executing as soon as it regains this object’s lock.
The notifyAll() method can be called only by a thread that is the current owner of this object’s lock. A thread holds the lock on this object while it is executing a synchronized instance method of the object or executing the body of a synchronized statement that synchronizes on the object.
A thread can also hold the lock for a Class object if it is executing a synchronized static method of that class. This method is final, so it cannot be overridden by subclasses.
public String toString();
public String toString() method returns a generic string representation of this object. The method returns a String that consists of the object’s class name, an “at” sign and the unsigned hexadecimal representation of the value returned by the object’s hashCode() method.
Many classes override the toString() method to provide a string representation that is specific to that type of object. Any subclass can override the toString() method; the overriding method should simply return a String that represents the contents of the object with which it is associated.
This method returns the string representation of this object.
public final native void wait();
public final native void wait() method causes a thread to wait until it is notified by another thread to stop waiting. When wait() is called, the thread releases its lock on this object and waits until another thread notifies it to wake up through a call to either notify() or notifyAll(). After the thread is awakened, it has to regain the lock on this object before it can resume executing.
The wait() method can be called only by a thread that is the current owner of this object’s lock.
A thread holds the lock on this object while it is executing a synchronized instance method of the object or executing the body of a synchronized statement that synchronizes on the object. A thread can also hold the lock for a Class object if it is executing a synchronized static method of that class.
This method is final, so it cannot be overridden by subclasses.
public final native void wait(long millis);
public final native void wait(long millis) method causes a thread to wait until it is notified by another thread to stop waiting or until the specified amount of time has elapsed, whichever comes first. When wait() is called, the thread releases its lock on this object and waits until another thread notifies it to wake up through a call to either notify() or notifyAll().
If the thread is not notified within the specified timeout period, it is automatically awakened when that amount of time has elapsed. If millis is zero, the thread waits indefinitely, just as if wait() had been called without a timeout argument. After the thread is awakened, it has to regain the lock on this object before it can resume executing.
The wait() method can be called only by a thread that is the current owner of this object’s lock. A thread holds the lock on this object while it is executing a synchronized instance method of the object or executing the body of a synchronized statement that synchronizes on the object. A thread can also hold the lock for a Class object if it is executing a synchronized static method of that class.
This method is final, so it cannot be overridden by subclasses.
Parameter
millis – The maximum number of milliseconds to wait.
public final native void wait(long millis, int nanos);
public final native void wait(long millis, int Nanos) method causes a thread to wait until it is notified by another thread to stop waiting or until the specified amount of time has elapsed, whichever comes first.
When wait for () is called, the thread releases its lock on this object and waits until another thread notifies it to wake up through a call to either notify() or notifyAll(). If the thread is not notified within the specified period, it is automatically awakened when that amount of time has elapsed. If millis and Nanos are zero, the thread waits indefinitely, just as if wait() had been called without any arguments. After the thread is awakened, it has to regain the lock on this object before it can resume executing.
The wait() method can be called only by a thread that is the current owner of this object’s lock. A thread holds the lock on this object while it is executing a synchronized instance method of the object or executing the body of a synchronized statement that synchronizes on the object. A thread can also hold the lock for a Class object if it is executing a synchronized static method of that class.
Note that Sun’s reference implementation of Java does not attempt to implement the precision implied by this method. Instead, it rounds to the nearest millisecond (unless millis is 0, in which case it rounds up to 1 millisecond) and calls wait(long).
This method is final, so it cannot be overridden by subclasses.
Parameter
millis – The maximum number of milliseconds to wait.
Nanos – An additional number of nanoseconds to wait.
protected native Object clone();
protected native Object clone() method clones an object. A clone of an object is another object of the same type that has all of its instance variables set to the same values as
the object being cloned. In other words, a clone is an exact copy of the original object.
The clone() method of Object creates a new object that is a clone of this object. No constructor is used in creating the clone. The clone() method only clones an object if the class of that object indicates that its instances can be cloned.
A class indicates that its objects can be cloned by implementing the Cloneable interface.
Although array objects do not implement the Cloneable interface, the clone() method works for arrays. The clone of an array is an array that has the same number of elements as the original array, and each element in the cloned array has the same value as the corresponding element in the original array. Note that if an array element contains an object reference, the cloned array contains a reference to the same object, not a copy of the object.
A subclass of Object can override the clone() method in Object to provide any additional functionality that is needed. For example, if an object contains references to other objects, the clone() method should recursively call the clone() methods of all the referenced objects. An overriding clone() method can throw a CloneNotSupportedException to indicate that particular objects cannot be cloned.
This method returns a clone of this object.
protected void finalize();
protected void finalize() method is called by the garbage collector when it decides that an object can never be referenced again. The method gives an object a chance to perform any cleanup operations that are necessary before it is destroyed by the garbage collector.
The finalize() method of Object does nothing. A subclass overrides the finalize() method to perform any necessary cleanup operations. The overriding method should call super.finalize() as the very last thing it does so that any finalize() method in the superclass is called.
When the garbage collector calls objects to finalize() method, the garbage collector does not immediately destroy the object because the finalize() method might do something that results in a reference to the object.
Thus the garbage collector waits to destroy the object until it can again prove it is safe to do so. The next time the garbage collector decides it is safe to destroy the object, it does so without calling finalize() again.
In other words, the garbage collector never calls the finalize() method more than once for a particular object.
Remember, declaring a variable to hold an object does not create the object. The variable just holds the reference to the object.
A finalize() method can throw any kind of exception. An exception causes the finalize() method to stop running. The garbage collector then catches and ignores the exception, so it has no further effect on a program.
How to create Objects
To create an object, we need to use the new keyword followed by the object’s class or type with optional argument lists in the parenthesis. These arguments are passed to the constructor of the class.
ComplexNumber c=new ComplexNumber(3.0,1.414);
Other ways to create objects
- We can create a String object by enclosing the characters in a double quote. like-
String myStr="I love Java"; // This is the shortcut for String Objects only
- By calling the newInstance() method of a class object. We use them generally in the dynamic loading of classes.
- Objects can also be created by deserializing them. That is recreating an object that had its state saved via serialization.
An Object:
An instance of a class is called an object. An object in java essentially means a block of memory that contains space to store all the instance variables. Thus, Objects and instances are interchangeable in java.
So creating an object is referred to as the instantiation of an object. In an object-oriented programming language, Objects can communicate between themselves using message. They know which message is for which object and how to interact with it. The message is sent to the object to performing some operation.
The object is having data and behaviors. The linking and bonding between data and operations on these data are known as encapsulation. (so an object is an amalgam of data and code). These data can only be manipulated using these operations. In other words, object’s data values are not directly accessed from outside, instead, they are accessed via the object’s behaviors.
So an object is having some private data values and public behaviors to manipulate the data. Calling a specific method in an object is referred to as sending a message. Objects can be created using the new operator. The new operator creates an object of the specified class and returns the reference of that object.
Construction of an Object
MyClass mc=new MyClass();
//or
MyClass mc;//declare the object
mc=new MyClass();//instantiate the object
where My class- is the provider class,
mc is the object reference of the MyClass,
new creates the instance of the provider class,
MyClass() is the constructor of the provider class. This is the default constructor or can be an overloaded constructor. We can create n numbers of objects by using this syntax:
MyClass mc1=new MyClass();
MyClass mc2=new MyClass();
MyClass mc3=new MyClass();
.....
MyClass mcn=new MyClass();
Each object holds some amount of memory space and has its copy of the instance variables of its class. It also signifies that any change to the variable of its one object does not affect the variables of another.
We can create two or more references to the same object.
MyClass mc1=new MyClass();
MyClass mc2;
mc2=mc1;
The user class or object is only bothered as the methods exposed by the provider class. It does not know anything about the implementation of the method. So an object of a provider class implements the details of what a method does. The provider class only knows how the method is implemented. Now to call a method to provide by the provider class, we need to use the dot operator to gain access to the provider class’s field if they are public.
like
mc.setFirstName("Joghn");
//or
String name=mc.getFirstName();
All variables of an object must be assigned some value before they are used. From outside of the class we can not assign/access the variables directly as most of the cases they are private. To do this we need to account object and a dot (.) operator.
objectName.variableName=value;
objectName.methodName(paramlist)
if the instance variables are public then we can follow this approach:
class MyClass{
public int x;
public int y;
}
class Test{
MyClass mc1=new MyClass();
mc1.x=10;
mc1.y=15;
}
if the instance variables are private then we can follow this approach:
class MyClass{
private int x;
private int y;
//we can define an argumented constructor
public MyClass(int x,int y)
this.x=x;
this.y=y;
}
//or we can define some getter or setter method
public void setValues(int x,int y)
this.x=x;
this.y=y;
}
class Test{
MyClass mc1=new MyClass(10,15);
//or
MyClass mc1=new MyClass();
mc1.setValues(10,15);
}
for function with a payload or argument to understand the process better, let’s start from right to left. we pass an argument called Joghn(string) to the method setFirstName.And call this method on the instance of the provider class -MyClass using a. (dot) operator to identify the specific object (stored in the memory) for this method call. This is how we use an object of the provider class. What happens internally:
once we created an object using a new operator, the required arguments need to be passed to the constructor. The JRE allocates sufficient memory to store the fields of the object and initializes its state. When initialization is done, the JRE returns a reference to the new object. So we can say the constructor returns an object reference to the object stored in memory. The default constructor takes no arguments and contains no code. It is provided automatically by the compiler if the developer has not provided any constructor in the class.
But this is theoretical, how to execute the object?
Well, we will execute the object of a provider class by inserting them into a container class and use the main method to trigger the execution.
Most Java applications may have any number of classes but they will surely have a single main that should trigger the execution.
An Example
public class MyContainerClass{
public static void main(String args[])
{
MyClass myObj=new MyClass();
myObj.setFirstName("Xavior");
}
}
To create an instance of class MyClass, We need to create a container class, then we can create the instance. The main is the starting function to kick of execution.
Guidelines for object creation:
- An object by convention starts with a small letter like obj.
- The object must be able to perform that method call.
The data member of an object
Each object keeps its storage for its data members, the data members are not shared among objects. We may have any number of classes, but they will have no impact on our program until and unless we create an object from that class.
class Myclass{
int i;
float f;
boolean b;
}
//this class does not anything unless we create an object using new operator
Myclass mc=new Myclass();
We can assign values to the data members by the object name(handle) by a dot(.) operator
like-
mc.i=10;
mc.f=1.0f;
mc.b=false;
our object may also contain other objects which we would like to call a function like-
System.out.println(“Hello Java”);
It means that select out from class System and call println() method.
Scope of Objects
Java objects do not have the same lifetimes as primitives. When we create a java object using new, it hangs around past the end of the scope.
{
String myStr=new String("java");
}
//end of the scope of myStr
The handle myStr vanishes at the end of the scope. However, the string object myStr was pointing to, is still occupying memory. In the above code, there is no way to access the object because it is out of scope post this code line.
Its turns out that because objects created with new operator stay around, as long as we want them. In Java, it makes sure the objects are available when they are needed. Once objects created they fill up memory that halts the program.
Java has a garbage collector, which is a process running in the background(low priority execution and does not interfere with program execution). The garbage collector looks at all the objects created by new and figures out which ones are not being referenced any further. Then it releases the memory for those objects.
This memory can be used by new objects. Thus a java coder never has to worry about reclaiming memory. This eliminates the problem of memory leakage where the programmer forgets to release memory.
How to Access the Objects?
Java objects are always accessed by their references. Java internally performs any necessary dereferencing. A dot (.) operator provides a mechanism to gain access to the object.
double magnitude=e.magnitude();
Let’s see how Object is used and how the assignment happens:
public class MyValue {
int x,y;
void getValue(int a, int b)
{
x=a;
y=b;
}
}
Lets us create our test class to check how the object invocation happens
public class MyTestClass {
static double distance;
public static void main(String[] args) {
// TODO Auto-generated method stub
MyValue p1=new MyValue();
MyValue p2 = p1;
MyValue p3 =new MyValue();
MyValue p4 =new MyValue();
p1.getValue(5,10);
p2.getValue(15,20);
p3.getValue(20,30);
p4.getValue(30,40);
System.out.println(p1.x);
System.out.println(p1.y);
p1=null;
System.out.println(p2.x);
System.out.println(p2.y);
p2=null;
int dx=p3.x-p4.x;
int dy=p3.y-p4.y;
distance=Math.sqrt(dx*dx+dy*dy);
System.out.println(distance);
}
}
code | Objects | Heap values |
---|---|---|
MyValue p1=new MyValue(); | One new object is created | the initial values 0,0 |
MyValue p2 = p1; | another object p2 gets created but both p1 and p2 are pointing to same object | the initial values 0,0 |
p1.getValue(5,10); | since p1 and p2 are referring same object, the x=5 and y=10 both p1.x=p2.x=5 and p2.y=p2.y=10 | |
p2.getValue(15,20); | Now, p2 is updating the value of the object. Since p2 and p1 are pointing to the same object, p1 also gets updated. both p1.x=p2.x=15 and p2.y=p2.y=20 | |
MyValue p3 =new MyValue(); MyValue p4 =new MyValue(); | p3 and p4 objects are created but they are different. | |
p3.getValue(20,30); | p3.x=20 and p3.y=30 | |
p4.getValue(30,40); | p4.x=30 and p4.y=40 | |
System.out.println(p1.x); System.out.println(p1.y); | Prints the values they are containing | |
p1=null; | p1 becomes null hence it is ready for garbage collected | |
System.out.println(p2.x); System.out.println(p2.y); | Prints the values they are containing | |
p2=null; | p2 becomes null hence it is ready for garbage collected |