Java中所有的类都是继承自Object类,因此Object类中的方法也是所有类可以使用的方法,本文将从以下角度对Java Object类方法进行详细阐述。
一、equals()方法
Object类中的equals()方法是用来判断两个对象是否相等的方法,其实现如下:
public boolean equals(Object obj) { return (this == obj); }
由于该方法只是简单地比较对象的地址是否相等,因此需要在自定义类中重写equals()方法,来判断两个对象的实际内容是否相等。
例如:
public class Person { private String name; private int age; //省略构造方法和其他方法 @Override public boolean equals(Object obj) { if (obj instanceof Person) { Person p = (Person) obj; return this.name.equals(p.name) && this.age == p.age; } return false; } }
在该示例中,如果两个Person对象的name和age都相等,则认为这两个对象相等。这样就可以使用equals()方法判断两个Person对象是否相等了。
二、hashCode()方法
hashCode()方法返回对象的哈希码,哈希码是一个int类型的数值。
Object类中的hashCode()方法实现如下:
public native int hashCode();
很显然,该方法返回的哈希码仅仅是对象的地址在内存中的位置。
在自定义类中需要重写hashCode()方法来获得合适的哈希码,一般使用对象的属性计算哈希码,如下所示:
public class Person { private String name; private int age; //省略构造方法和其他方法 @Override public int hashCode() { return Objects.hash(name, age); } }
在该示例中,使用Objects类的hash()方法来计算哈希码,该方法中可以传入多个属性,每个属性的哈希码都会参与计算,得出最终哈希码。
三、toString()方法
toString()方法返回对象的字符串表达形式,一般在输出对象时使用。Object类中的toString()方法实现如下:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
该实现方式可读性不高,因此在自定义类中一般需要重写toString()
例如:
public class Person { private String name; private int age; //省略构造方法和其他方法 @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
在该示例中,toString()方法返回了Person对象的属性信息,方便在输出时查看对象的实际信息。
四、getClass()方法
getClass()方法返回对象所属的类的Class对象,该对象包含了该类的一些信息,如类名、方法等。
例如:
public static void main(String[] args) { Person person = new Person(); Class clazz = person.getClass(); System.out.println(clazz.getName()); //输出Person类的类名 }
五、wait()、notify()、notifyAll()方法
这三个方法都是用来实现线程之间的通信的,使用时需要在synchronized关键字的保护下进行,每个方法的作用如下:
- wait()方法:将当前线程置于等待状态,并释放锁
- notify()方法:唤醒一个正在等待该对象的线程
- notifyAll()方法:唤醒所有正在等待该对象的线程
例如:
public class MyRunnable implements Runnable { private Object obj; public MyRunnable(Object obj) { this.obj = obj; } @Override public void run() { synchronized (obj) { try { System.out.println("线程" + Thread.currentThread().getName() + "开始等待..."); obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程" + Thread.currentThread().getName() + "被唤醒了!"); } } } public static void main(String[] args) { Object obj = new Object(); Thread t1 = new Thread(new MyRunnable(obj), "t1"); Thread t2 = new Thread(new MyRunnable(obj), "t2"); Thread t3 = new Thread(new MyRunnable(obj), "t3"); //启动三个线程 t1.start(); t2.start(); t3.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj) { obj.notify(); //obj.notifyAll(); //唤醒所有线程 } }
该示例中,三个线程分别对同一个对象进行了wait()操作,主线程在等待1s后唤醒一个线程。运行结果如下:
线程t2开始等待... 线程t1开始等待... 线程t3开始等待... 线程t1被唤醒了!
六、clone()方法
clone()方法是用来创建一个对象的副本的方法。在自定义类中需要重写clone()方法,并实现Cloneable接口,如下所示:
public class Person implements Cloneable { private String name; private int age; //省略构造方法和其他方法 @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
在该示例中,由于Object类中的clone()方法是protected类型的,因此需要在子类中实现一份public类型的clone()方法来进行克隆操作。使用时需要注意,在对象克隆完成后,克隆对象和原对象共享对象引用,因此需要进行深拷贝(也就是复制对象的内容而不是引用)操作。
七、finalize()方法
finalize()方法是Java在对象被垃圾回收前进行一些必要的清理工作的方法。一般不建议使用,因为垃圾回收是不确定时间的,可能并不会进行回收操作。
示例中不再赘述,此处略去。