Object类中方法的基本介绍

Object类是所有Java类的根父类。

如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类

先来看看帮助文档的介绍:

在这里插入图片描述


clone()方法

protected native Object clone() throws CloneNotSupportedException;

clone方法的作用就是创建并返回对象的一个副本,也就是copy。

创建同一个类的一个新对象,并将原有对象的属性值赋给新的对象(浅拷贝)。

一个类的对象想要调用clone方法,该类必须实现Cloneable接口,否则会抛出CloneNotSupportedException异常,然后重写clone方法,调用父类的clone方法,返回克隆的对象(super.clone())。数组默认是支持clone的

public class ObjectTest01 {

    public static void main(String[] args) {
        Student student1 = new Student();
        String[] hobbies = {"足球","篮球","羽毛球"};
        student1.setAge(18);
        student1.setName("张三");
        student1.setHobbies(hobbies);
        Student student2 = (Student) student1.clone();
        System.out.println(student1);
        System.out.println(student2);
    }

}

class Student implements Cloneable{
    private int age;
    private String name;
    private String[] hobbies;

    public Student(){
        super();
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String[] getHobbies() {
        return hobbies;
    }

    public void setHobbies(String[] hobbies) {
        this.hobbies = hobbies;
    }

    @Override
    public Object clone() {
        try{
            return super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString() {
        return "Student@" + this.hashCode() + "{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", hobbies=" + Arrays.toString(hobbies) +
                '}';
    }
    
}

打印结果如下:

此时成功拷贝了student对象,但是是浅拷贝,就是赋值操作,如果对引用类型的属性中的值进行操作,原对象中的值也会被改变。如果想要实现完全的拷贝,深拷贝,只需要将引用类型的属性(成员变量)也clone一遍进行赋值即可,当然该成员变量也必须实现Cloneable接口,重写clone方法。

clone方法修改如下:

 public Object clone() {
        try {
            Student student = (Student) super.clone();
            student.setHobbies(student.getHobbies().clone());
            return student;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

toString()方法

public String toString();

当我们使用System.out.println()打印对象时,就是调用的toString方法。

如果不重写toString(),那么默认调用的就是Object类中的toString方法,输出对象类型及地址。
在这里插入图片描述

但是我们在实际打印对象时,往往希望看到的是对象中的内容,而不是对象的地址,所以我们需要重写该方法。

public class Person{
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +"age=" + age +", name='" + name +"}";
    }
}

getClass()方法

public final native Class<?> getClass();

getClass()名称和getXX()类似,作用是获取当前对象的运行时类对象。通过类对象可以获取到类中的属性,方法,名称,类加载器等内容。

public class GetClassTest {

    public static void main(String[] args) {
        String s = "1111";
        System.out.println(s.getClass());
		
	    //s.getClass().getDeclaredField();
        //s.getClass().getMethod();
        //s.getClass().getClassLoader();
    }

}

在这里插入图片描述


equals()方法

public boolean equals(Object obj){}

Object类中equals方法的底层就是用运算符"=="。
在这里插入图片描述
比较的是两个对象的地址值是否相同。在实际开发中,常常需要重写equals方法(一般比较对象的内容)。

比如:

public class Student{
    private int age;
    private String name;
    
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    
     public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
  	
    @Overried
    public boolean equals(Object obj){
        if(this == student){
            return true;
        }
        if(obj != null && this.getClass() == obj.getClass()){
            Student student1 = (Student) obj;
            //如果属性也是引用类型,那么需要调用重写后的equals来比较
            return age == worker.age && name.equals(worker.name);
        }
        return false;
    }
    
}

hashCode()方法

 public native int hashCode();

hashCode()方法作用是返回对象的哈希码值。这个方法是为了支持哈希表结构,例如HashMap。

注意:

  1. 一次java程序的执行中,同一个对象多次调用hashCode方法,产生的哈希码值一定是相同的,前提是,前提是将对象进行equals比较时所用的信息没有被修改。但是,在多次启动相同的java程序时,同一对象调用hashCode方法产生的哈希值不需要保持相同。
  2. 如果根据equals方法两个对象相等,那么它们的哈希码值一定是相同的;如果equals方法比较两个对象不相等,那么哈希码值一定不同。但是拥有相同哈希码值的对象不一定相等。

所以重写equals方法时,通常也需要重写hashCode方法,以维护其通用性。

public class HashCodeTest {

    public static void main(String[] args) {
        String s = "1111";
        System.out.println("s: " + s.hashCode());

        String s1 = "2222";
        System.out.println("s1: " + s1.hashCode());
        System.out.println("s == s1? " + s.equals(s1));

        String s2 = "2222";

        System.out.println("s1 == s2? " + s1.equals(s2));
        System.out.println("s2: " + s2.hashCode());
    }

}


notify()方法和notifyAll()方法

public final native void notify();

唤醒单个当前正在等待对象监视器的线程,且唤醒的选择性是任意的。

public final native void notifyAll();

唤醒当前正在对待对象监视器的所有线程。


wait()方法

public final native void wait(long timeout) throws InterruptedException;

让当前线程等待,直到被当前对象的其它线程调用notify()或者notifyAll()唤醒,或者等待超过指定时间。timeout单位为毫秒

public final void wait() throws InterruptedException {
    wait(0);
}

让当前线程等待,直到被当前对象的其它线程调用notify()或者notifyAll()唤醒。这里实际就是调用上一个方法,但是指定时间为0ms。

public final void wait(long timeout, int nanos) throws InterruptedException{
    if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
}

让当前线程等待,直到被当前对象的其它线程调用notify()或者notifyAll()唤醒,或者经过了指定的时间。

wait(long timeout, int nanos)方法和wait(long timeout)方法功能是相同的,只是前者能够更精准地控制时间。timeout单位是毫秒,nanos的单位是纳秒,且输入范围是[0.999999],即不超过1毫秒。

源码上面的注释写的是以纳秒为单位的等待时间由:1000000*timeout+nanos 给出,但实际上只要传入的参数nanos大于0时,等待时间就增加1ms。这里是jdk8版本的代码,可能是由于纳秒级的等待时间太短,直接加1ms。

在更早的版本中:

public final void wait(long timeout, int nanos) throws nterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
	
        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }
		
        if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
            timeout++;
        }

        wait(timeout);
    }

当毫秒级等待时间timeout为0且纳秒级等待时间nanos不为0时,等待时间增加1ms。

当nanos大于等于半毫秒时,等待时间增加1ms。

除以上两种情况以外,等待时间不做额外的增加。

finalize()方法

protected void finalize() throws Throwable{}

我们创建的对象都是存储在堆空间中的,并且由引用类型的变量指向这些对象。但是,如果一味地创建对象会导致堆空间被占满甚至溢出,所以java提供了垃圾回收机制。当一个对象没有任何引用指向它时,就认为它是没有用了,这时垃圾回收机制会被触发对其进行回收操作。但是,垃圾回收机制给这些无用的对象一个喘息的机会,在实际回收这些对象之前,会调用finalize()方法。如果重写了finalize方法,让新的引用变量指向要回收的对象,此时这些对象又将被激活,而不被回收。

测试一下:

public class FinalizeTest {

    public static void main(String[] args) {
        People people = new People("chunni",18);
        System.out.println(people);
        people = null;//此时没有引用执行该对象了
        System.gc();//强制释放对象,通知垃圾收集器回收该对象
    }

}

class People{
    private String name;
    private int age;

    public People() {
    }

    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("准备回收对象" + this);
        //People people = this;
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在这里插入图片描述

finalize方法中可以进行一切操作,甚至重新激活要回收的对象。但是一般调用finalize方法后就进行清理操作,且由对象自动调用。不建议手动调用finalize方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值