All you need to know about the Object class
Sun, 17 Nov 2024
Here, we will be discussing about the Object class with its commonly used methods.
Object greet = "Hello";
Object bye = new StringBuilder("Bye");
There are 9 methods available in Object class. We can categorize them based on customization.
getClass()
, notify()
, notifyAll()
, wait()
.toString()
, equals()
,hashCode()
, clone()
, finalize()
Let us explain those methods one by one based on commonly used. We will be using these two classes as the base for some of our methods.
// located in package z_medium
public class Medium {
static class Point{
final int x;
final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
static class Circle {
final Point center;
final float radius;
public Circle(Point center, float radius) {
this.center = center;
this.radius = radius;
}
}
public static void main(String[] args) {
}
}
System.out.println(circle);
is actually interpreted as System.out.println(circle.toString());
"Result: "+circle
is interpreted as "Result: "+circle.toString()
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
Circle
class, it will be printing like this:System.out.println();
final Point point = new Point(1, 2);
Circle circle = new Circle( point, 5f );
System.out.println(circle); // z_medium.Medium$Circle@4dd8dc3
public class Medium {
static class Point{
final int x;
final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "("+x+", "+y+")";
}
}
static class Circle {
final Point center;
final float radius;
public Circle(Point center, float radius) {
this.center = center;
this.radius = radius;
}
@Override
public String toString() {
return "center: " + center + ", radius: " + radius;
}
}
public static void main(String[] args) {
final Point point = new Point(1, 2);
Circle circle = new Circle( point, 5f );
System.out.println(circle); // center: (1, 2), radius: 5.0
}
}
Point
as well, since we are using it in the toString()
method of the Circle
class.public boolean equals(Object obj) {
return (this == obj);
}
equals()
can be very bad since it will return false even if the two objects have exactly the same values.Point pointOne = new Point(1, 2);
Point pointTwo = new Point(1,2);
System.out.println( pointOne.equals(pointTwo) ); // false
public class Medium {
static class Point{
final int x;
final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object obj) {
if(this == obj) { // same object -- (1)
return true;
}
if( !(obj instanceof Point other)) {// different classes --- (2)
return false;
}
return x == other.x && y == other.y;//comparing the fields -- (3)
}
}
public static void main(String[] args) {
final Point pointOne = new Point(1, 2);
final Point pointTwo = new Point(1,2);
final Point pointThree = new Point(2,3);
final String john = "John";
System.out.println( pointOne.equals(pointOne) ); // true (1)
System.out.println( pointOne.equals(john) ); // false (2)
System.out.println( pointOne.equals(pointTwo) ); // true (3)
System.out.println( pointTwo.equals(pointThree) ); // false (3)
}
}
equals(Object)
for comparing. We can’t use ==
.public static void main(String[] args) {
final Point pointOne = new Point(1, 2);
final Point pointTwo = new Point(1,2);
final Point pointThree = new Point(2,3);
List<Point> pointList = List.of(pointOne, pointTwo, pointThree);
final Map<Point, Integer> pointCountMap = new HashMap<>();
for(Point point: pointList){
pointCountMap.put(point, pointCountMap.getOrDefault(point, 0) + 1);
}
for(Map.Entry<Point, Integer> entry: pointCountMap.entrySet()){
System.out.println(entry.getKey() + ": " + entry.getValue());
}
/*
Output is:
(2, 3): 1
(1, 2): 1
(1, 2): 1
*/
}
toString()
and equals()
method in the Point class. But still the count is not what we expected. This is because Map uses the hashCode of the object internally when we use a custom class as key.hashCode()
uses the memory location. So, for different objects having same value, their hash-code is different. As a result they are treated differently.hashCode()
function if the properties are same.static class Point{
// other codes
@Override
public int hashCode() {
// return super.hashCode(); // default implementation
return 11 * x + 31 * y;
// return Objects.hash(x, y); // or use this
// return 1; // will work. find yourself or let me know in comment
}
}
(2, 3): 1
(1, 2): 2
If two objects are equal, then their hash-code have to be the same. But even the hash-code of two objects is same, they may be different. Do you know why?
String greet = "Hello";
System.out.println( greet.getClass() ); // class java.lang.String
Object objStr = greet; // ------ (2)
System.out.println( objStr.getClass() ); // class java.lang.String
Object obj = new Object();
System.out.println( obj.getClass() ); // class java.lang.Object
getClass()
still prints the class java.lang.String since it is the runtime type.clone()
method can do it for us.public class Medium {
static class Point implements Cloneable{
int x, y;
// constructor and toString
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class Circle implements Cloneable{
Point center;
float radius;
// constructor and toString
@Override
public Object clone() throws CloneNotSupportedException {
Circle circle = (Circle) super.clone();
circle.center = (Point) center.clone(); // ------------------ (a)
return circle;
}
}
public static void main(String[] args) {
Circle circle = new Circle( new Point(1, 2), 3.5f );
System.out.println(circle); // center: (1, 2), radius: 3.5
try {
Circle cloned = (Circle) circle.clone();
System.out.println(cloned); // center: (1, 2), radius: 3.5
circle.center.x = 10;
// System.out.println(cloned.center.x); // 10 --> without (a)
System.out.println(cloned.center.x); // 1
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
Cloneable
interface.clone()
method.Object
class.java.util.concurrent
for multithreading.Artist
which will generate and draw a point in a consistent way.public class Medium {
static class Point {
int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
@Override
public String toString() { return "("+x+", "+y+")"; }
}
static class Artist {
private final Point point = new Point(0,0);
private boolean isCurrentPointDrawn = true;
public synchronized void productNextPoint(int value) {
while (!isCurrentPointDrawn) {
try {
wait(); // Wait if current point isn't drawn yet
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
try{ Thread.sleep(2000); }catch (InterruptedException e){}
point.x += value;
point.y += value;
System.out.println("Produced: " + point);
isCurrentPointDrawn = false;
notify(); // Notify that point is available to draw
}
public synchronized void drawCurrentPoint() {
while (isCurrentPointDrawn) {
try {
wait(); // Wait if no point is available to draw
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println("Drawn: " + point);
isCurrentPointDrawn = true;
notify(); // Notify the waiting producer that point has been drawn
}
}
public static void main(String[] args) {
final Artist resource = new Artist();
final int noOfPoints = 3;
Thread producerThread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < noOfPoints; i++) {
resource.productNextPoint(i);
}
}
});
Thread consumerThread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < noOfPoints; i++) {
resource.drawCurrentPoint();
}
}
});
producerThread.start();
consumerThread.start();
}
}
Produced: (0, 0)
Drawn: (0, 0)
Produced: (1, 1)
Drawn: (1, 1)
Produced: (3, 3)
Drawn: (3, 3)
That's the end!!!
This is a comment 1.
This is a comment 2.