object类

Object类是所有类的父类,即直接或间接的继承lava.lang.Object类

由于所有的类都继承在Object类,因为省略了extends Object关键字

该类中主要有以下方法:

  • toString()
  • getClass()
  • equals()
  • clone()
  • finalize()

1、clone()方法

protected native Object clone() throws CloneNotSupportedException;

clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象。所谓的复制对象, 首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象。那么在java语言中,有几 种方式可以创建对象呢?

  • 使用new操作符创建一个对象
  • 使用clone方法复制一个对象

那么这两种方式有什么相同和不同呢? new操作符的本意是分配内存。程序执行到new操作符时, 首 先去看new操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后, 再调用构造函数,填充对象的各个域,这一步叫做对象的初始化,构造方法返回后,一个对象创建完 毕,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用操纵这个对象。而clone在第一步 是和new相似的, 都是分配内存,调用clone方法时,分配的内存和源对象(即调用clone方法的对象) 相同,然后再使用原对象中对应的各个域,填充新对象的域, 填充完成之后,clone方法返回,一个新 的相同的对象被创建,同样可以把这个新对象的引用发布到外部。

package com.object;

import java.util.Date;

public class Person implements Cloneable{
    private String name;
    private int age;
    private Date date;
    public Person() {
    }

    public Person(String name, int age, Date date) {
        this.name = name;
        this.age = age;
        this.date = date;
    }

    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;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    @Override
    public Object clone() throws CloneNotSupportedException{
        Person cloned = (Person)super.clone();
        cloned.date = (Date)date.clone();
        return cloned;
//        return (Person)super.clone();

    }
}
package com.object;

import java.util.Date;

public class Demo01 {
    public static void main(String[] args) throws CloneNotSupportedException {

        Person p = new Person("zhang",23,new Date());
        Person p1 = (Person) p.clone();
        Person p2 =p;
        System.out.println(p);
        System.out.println(p2);
        System.out.println(p1);
        String result = p.getName() == p1.getName()?"clone是浅拷贝":"clone是深拷贝";
        String result2 = p.getDate() == p1.getDate()?"clone是浅拷贝":"clone是深拷贝";
        System.out.println(result);
        System.out.println(result2);

    }
}

2、toString()方法

public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

Object类的toString方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at标记符“@”和此对象哈希码的无符号十六进制表示组成。

该方法用得比较多,一般子类都有覆盖。

public static void main(String[] args){
	Object o1 = new Object();
	System.out.println(o1.toString());
}

3、getClass()方法

public final native Class<?> getClass();

返回此Ojbect运行时的类型。

不可重写,要调用一般于getName()联合使用,如getClass().getName();

public static void main(String[] args) {
    Object o = new Object();
    System.out.println(o.getClass());
    //class java.lang.Object
}

4、finalize()方法

protected void finalize() throws Throwable { }

该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。 Java允许在类中定义一个名为finalize()的方法。它的工作原理是:一旦垃圾回收器准备好释放对象占用 的存储空间,将首先调用其finalize()方法。并且在下一次垃圾回收动作发生时,才会真正回收对象占用 的内存。 关于垃圾回收,有三点需要记住:

1、对象可能不被垃圾回收。只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不 到释放。

2、垃圾回收并不等于“析构”。

【科普:析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完 毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟 了一片内存空间,delete会自动调用析构函数后释放内存)。】

3、垃圾回收只与内存有关。使用垃圾回收的唯一原因是为了回收程序不再使用的内存。 finalize()的用途:

无论对象是如何创建的,垃圾回收器都会负责释放对象占据的所有内存。

这就将对finalize()的需求限制到一种特殊情况,即通过某种创建对象方式以外的方式为对象分配了存储 空间。不过这种情况一般发生在使用“本地方法”的情况下,本地方法是一种在Java中调用非Java代码的方式。

5、equals()方法

public boolean equals(Object obj) {
	return (this == obj);
}

6、hashCode()方法

public native int hashCode();

返回该对象的哈希码值。 该方法用于哈希查找,可以减少在查找中使用equals的次数,重写了equals方法一般都要重写 hashCode方法。这个方法在一些具有哈希功能的Collection中用到。 一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash Code() == obj2.hashCode(),但是 hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。

7、 wait()方法 —学完多线程再回来补充

8、notify()方法 —学完多线程再回来补充