1.定义

object是Java的顶级父类。。

在Java中提供了一个object类,Object类是Javajava.lang包下的核心类,它是所有类的父类,即每个类都直接或间接继承自该类,因此object类通常被称为超类,基类或根类。当定义一个类时,如果没有使用extends此关键字位于这个类显式的指定父类,那么该类会默认继承object类。

//以下两种类的定义的最终效果是完全相同的:
class Person { }
class Person extends Object { }

object中自定义了一些方法,如下表所示:

方法声明 功能描述
clone() 保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。
getClass() final方法,返回Class类型的对象,反射来获取对象。
toString() 该方法用得比较多,一般子类都有覆盖,来获取对象的信息。
finalize() 该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
equals() 比较对象的内容是否相等
hashCode() 该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
wait() wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
notify() 该方法唤醒在该对象上等待的某个线程。
notifyAll() 该方法唤醒在该对象上等待的所有线程。

(1)tostring

class Animal{
    protected Animal() {
        System.out.println("我是一只动物");
    }

}
class Dog extends Animal{
    public Dog(){
    }
}
public class test extends Object{
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog.toString());
    }
}

alt

上述第十四行代码,调用了Animal对象的toString()方法,虽然Animal类中没有定义这个方法,但是程序并没有报错。这是因为Animal类默认继承了Object类,在Object类中定义了toString方法,在该方法中输出了对象的基本信息。

object类中定义的toString()方法输出信息具体格式如下:

public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    
① getClass().getName()代表返回对象属性的类名,即包名+类名的全限定名称。
② hashCode()代表返回该对象的哈希值。
③ Integer.toHexString(hashCode())代表将该对象的哈希值用十六进制进行表示。
其中,hashCode()是Object类中定义的一个方法,这个方法将对象的地址进行哈希运算,返回一个int类型的哈希值。

在实际的开发中,通常希望toString()方法返回的不仅仅是对象的基本信息,还是一些特别有用的信息,为此可以重写object中的toString()方法来实现。如下:

class Animal{
    public String toString(){
        return "这是一只动物";
    }

}
class Dog extends Animal{
    public Dog(){
    }
}
public class test extends Object{
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog.toString());
    }
}

alt

上述代码重写了Object中的同totring()方法。

也可以如下:

class Person{
    private String name;
    private Integer age;

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

(2) equal()方法

String类对象比较 使用的是 equals()方法,实际上String类的equals()方法就是覆写 Object类中的equals()方法。

  • 基本数据类型的比较用 == (如: a == 3,b == 4, a == b,比较的是值是否相等)
  • 引用类型数据比较:调用 equals()方法进行比较

用equals( )来比较对象内容是否相同:

class Person{
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}
public class test extends Object{
    public static void main(String[] args) {
        Person person1 = new Person("张三", 18);
        Person person2 = new Person("张三", 18);
        System.out.println(person1.equals(person2));
    }
}

alt

两个对象person1和person2的内容明明相等,应该是true呀?怎么会是false?

因为此时直接调用equals()方法默认进行比较的是两个对象的地址。

在源码中,传递来的Object对象和当前对象比较地址值,返回布尔值。

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

但是,new一下就会在堆上创建新空间,两个对象地址自然不会相同,所以为false。

但是在判断两个对象是否相等时,比如要判断一个Person类的两个对象的姓名是否相同时,此时要重新覆写equals()

还是上面的例子,覆写equals()方法(idea中可以直接使用快捷键进行重写)

class Person{
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) && Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
public class test extends Object{
    public static void main(String[] args) {
        Person person1 = new Person("张三", 18);
        Person person2 = new Person("张三", 18);
        System.out.println(person1.equals(person2));
    }
}

alt

所以,引用类型的数据在进行比较时,应该先覆写equals()方法,不然比较的还是两个对象的堆内存地址值,必然不会相等.

(3) hashCode()

使用hashCode可以计算具体的对象位置,也就是内存地址,然后调Integer.toHexString()方法,将这个地址以16进制输出。

import java.util.Objects;

class Person{
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

}
public class test extends Object{
    public static void main(String[] args) {
        Person person1 = new Person("张三", 18);
        Person person2 = new Person("张三", 18);
        System.out.println(person1.hashCode());
        System.out.println(person2.hashCode());
    }
}

alt

从上述截图中我们可以发现,person1和person2的hashCode值是不一样的。说明直接这样中hashCode是不行的,那就要重新实现一个hashCode。

import java.util.Objects;

class Person{
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

}
public class test extends Object{
    public static void main(String[] args) {
        Person person1 = new Person("张三", 18);
        Person person2 = new Person("张三", 18);
        System.out.println(person1.hashCode());
        System.out.println(person2.hashCode());
    }
}

alt

然后运行代码试试看,果然重写之后,内存地址相同了。

所以,hashCode是用来定位位置的

idea使用快捷键alt+insert可以快速实现重写。

alt