Java-Object根父类

148 阅读4分钟

所有类的父类,每个类都使用 Object作为超类。

  • Object类型的变量与除Object以外的任意引用数据类型的对象都多态引用
  • 所有对象(包括数组)都可以调用object类的方法。
  • 如果一个类没有特别指定父类,那么默认则继承自Object类。例如:
public class MyClass /*extends Object*/ {
  	// ...
}

Object类的五个方法:

(1)toString()

方法签名:public String toString() 如何调用

  • 通过对象.toString调用
  • System.out.println方法在打印对象时自动调用
  • 在对象与字符串进行"+"拼接时

因为Java的引用数据类型的变量中存储的实际上时对象的内存地址,但是Java对程序员隐藏内存地址信息,所以不能直接将内存地址显示出来,所以当你打印对象时,JVM帮你调用了对象的toString()。

例如自定义的Person类:


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

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

默认情况下,toString()返回的是“对象的运行时类型 @ 对象的hashCode值的十六进制形式"

一般情况下,我们建议所有子类都重写toString()这个方法。手动重写(根据自己的需要)或Alt+Insert自动生成

重写后的toString会return该类的全部属性和属性值,也可根据自己需求更改(类似于之前所写的getInfo();)

(2)getClass()

public final Class<>   getClass():获取对象的运行时类型

因为Java有多态现象,所以一个引用数据类型的变量的编译时类型与运行时类型可能不一致,因此如果需要查看这个变量实际指向的对象的类型,需要用getClass()方法

public static void main(String[] args) {
    Object obj = new Person();
    System.out.println(obj.getClass());//运行时类型,结果是Person
}

(3)equals()

public boolean equals(Object obj):
返回值类型:boolean

作用:用于比较 “当前对象” 和 "obj对应的实参对象" 是否 “相等”。

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

Alt + Insert,选择equals and hashCode

如果子类没有重写Object类的equals方法,Object类中equals默认就是比较对象的地址,等价于 “==”。

没重写Object类的equals方法前:

public class student {
    public static void main(String[] args) {
        student s1 = new student("张三",18,89);
        student s2 = new student("张三",18,89);
        student s3 = new student("张三",24,100);
        System.out.println(s1 == s2); //false
        System.out.println(s1 == s3); //false
        System.out.println(s2 == s3); //false

        System.out.println(s1.equals(s2)); //false
        //子类没有重写Object类的equals方法,Object类中equals默认就是比较对象的地址,等价于 “==”
    }
    
    private String name;
    private int age;
    private int score;

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

重写Object类的equals方法后:

public class student {
    public static void main(String[] args) {
        student s1 = new student("张三",18,89);
        student s2 = new student("张三",18,89);
        student s3 = new student("张三",18,100);
        System.out.println(s1 == s2); //false
        System.out.println(s1 == s3); //false
        System.out.println(s2 == s3); //false

        System.out.println(s1.equals(s2)); //子类重写equals了,输出true
        System.out.println(s1.equals(s3)); //重写没重写都是false,因为我重写的是要比较name、age、score三个,此处只有name相同,所以是false
    }

    private String name;
    private int age;
    private int score;

    //子类重写equals
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        student student = (student) o;
        return age == student.age && score == student.score && Objects.equals(name, student.name);
    }

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

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

(4)hashCode()

public int hashCode():返回每个对象的hash值。

如果重写equals,那么通常会一起重写hashCode()方法,hashCode()方法主要是为了当对象存储到哈希表(后面集合章节学习)等容器中时提高存储和查询性能用的,这是因为关于hashCode有两个常规协定:

  • ①如果两个对象的hash值是不同的,那么这两个对象一定不相等;
  • ②如果两个对象的hash值是相同的,那么这两个对象不一定相等。

重写equals和hashCode方法时,要保证满足如下要求:

  • ①如果两个对象调用equals返回true,那么要求这两个对象的hashCode值一定是相等的;
  • ②如果两个对象的hashCode值不同的,那么要求这个两个对象调用equals方法一定是false;
  • ③如果两个对象的hashCode值相同的,那么这个两个对象调用equals可能是true,也可能是false
public static void main(String[] args) {
    System.out.println("Aa".hashCode());//2112
    System.out.println("BB".hashCode());//2112
}

(5)finalize()

protected void finalize():用于最终清理内存的方法

作用:
当垃圾回收器(GC)确定不存在对该对象的更多引用(确定某个对象是垃圾对象)时,
由对象的垃圾回收器调用此方法。子类重写 finalize 方法,以配置系统资源或执行其他清除。

结论:
这个方法不是由程序员调用的,是GC调用,自动调用。
如果子类要重写它,目的只有一个:配置系统资源或执行其他清除。
系统资源:IO流、数据库连接等

补充:
每一个对象的finalize方法会被调用几次?
肯定是一次。
就算对象在finalize方法中被复活了,下次GC就不调用它的finalize方法了。