Object
Object类的常见方法?
在Java中,经常提到一个词“万物皆对象”,其中的“万物”指的是Java中的所有浏类,而这些类都是Object类的子类
Object主要提供11个方法,大致可以分为六类:
对象比较:
public native int hashCode():native方法,用于返回对象的哈希码
public native int hashCode();
按照约定,相等的对象必须具有相等的哈希码。
如果重写了equals方法,就应该重写hashCode方法。
可以使用Objects.hash()方法来生成哈希码。
public int hashCode(){
return Objects.hash(name,age);
}
public boolean equals(Object obj):用于比较2个对象的内存地址是否相等。
public boolean equals(Object obj){
return (this == obj);
}
如果比较的是两个对象的值是否相等,就要重写该方法,比如String类,Integer类等都重写了该方法。
举个例子,假如有一个Person类,我们认为只要年龄和名字相同,就是同一个人,那么就可以这样重写equals方法。
class Person1{
private String name;
private int age;
//省略getter和setter方法
public boolean equals(Object obj){
if(this == obj){
return true;
}
if(obj instanceof Person1){
Person1 p = (Person1)obj;
return this.name.equals(p.getName())&& this.age == p.getAge();
}
return false;
}
}
对象拷贝:
protected native Object clone() throws CloneNotSupportedException:native方法,返回此对象的一个副本,默认实现只做浅拷贝,且类必须实现Cloneable接口
Object本身没有实现Cloneable接口,所以在不重写clone方法的情况下直接调用方法会发生CloneNotSupportedException异常
对象转字符串:
public String toString();返回对象的字符串表示。
默认实现发回类名@哈希码的十六进制表示,但通常会被重写以返回更有意义的信息
public String toString(){
return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
比如说一个Person类,我们可以重写toString方法,返回一个有意义的字符串:
public String toString(){
return "Person{"+
"name='"+name+‘/’'+
".age=”+age+
'}';
}
当然了,这项工作也可以直接交给IDE,比如Intellij IDEA,直接右键选择Generate,然后选择toString方法,就会自动生成一个toString方法。
也可以交给Lombok,使用@Data注解,它会自动生成toString方法
数组也是一个对象,所以通常我们打印数组的时候,会看到诸如[I@1b4d3586这样字符串,这个就是int数组的哈希码。
多线程调度:
每个对象都可以调用Object的wait/notify方法来实现等待/通知机制。
我们来写一个例子:
public class WaitNotifyDemo{
public static void main(String [] args){
Object lock =new Object();
new Thread(()->{
synchronized(lock){
System.out.println("线程1:我要等待”);
try{
lock.wait();
}catch(InterruptedException e){
e.printStackTrace();;
}
System.out.println("线程1:我被唤醒了”);
}
}).start();
new Thread(()->{
synchronized(lock){
System.out.println("线程2:我要唤醒”);
lock.notify();
System.out.printLn("线程2:我已经唤醒了”);
}
}).start();
}
}
解释一下:
线程1先执行,它调用了lock.wait()方法,然后进入了等待状态
线程2后执行,它调用了lock.notify()方法,然后线程1被唤醒了。
1public final void wait() throws InterruptedException:调用该方法会导致当前线程等待,直到另一个线程调用此对象的notify()方法或notifyAll()方法
public final native void notify():唤醒在此对象监视器上等等待的单个线程,如果有多个线程等待,选择一个线程被唤醒。
public final native void notifyAll():唤醒在此对象监视器上等待的所有线程
public final native void wait(long timeout) throws InterruptedException:等待timeout毫秒,如果在timeout毫秒内没有被唤醒,会自动唤醒。
public final void wait(long timeout,int nanos) throws InterruptedException:更加精确了,等待timeout毫秒和nanos纳秒,如果在timeout毫秒和nanos纳秒内没有被唤醒,会自动唤醒。
反射:
public final native Class<?> getClass():用于获取对象的类信息,如类名。
比如说:
public class GetClassDemo{
public static void main(String[] args){
Person p =new Person();
Class<? extends Persons> aClass = p.getClass();
System.out.println(aClass.getName());
}
}
输出结果:
com.itwannger.Person
垃圾回收:
protected void finalize() throws Throwable:当垃圾回收器决定回收对象占用的内存时调用此方法。用于清理资源,但Java不推荐使用,因为它不可预测且容易导致问题,Java9开始弃用。