java Object 对象详解:equals、hashCode、toString、finalize 方法

equals方法

equals 和 == 的区别

  • == 是一个比较运算符,它可以判断基本类型,也可以判断引用类型。如果判断基本类型,判断的是值是否相等;如果判断的是引用类型,实际上判断的是地址是否相等,即判定是不是堆内存里的同一个对象
  • equals 是 Object 类中的方法,只能判断引用类型,Object 中的 equals 方法默认判断的是地址是否相等,和 == 号判断引用类型一样,但子类中往往会重写 equals 方法,用于判断内容是否相等。如 Integer、String 类就重写了 equals 方法

重写 Person 类中的 equals 方法

判断两个 Person 对象的内容是否相等,如果两个 Person 对象的各个属性值都一样,返回 true ,反之返回 false 。

public class Test {
    public static void main(String[] args) {
        Person p1 = new Person("zs", 28, '男');
        Person p2 = new Person("zs", 28, '男');
        System.out.println(p1.equals(p2));
    }
}

class Person {
    private String name;
    private int age;
    private char gender;

    public Person(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    // .... 省略属性的 get 和 set 方法

    // 重写 Object 中的 equals 方法
    public  boolean equals(Object obj){
        // 如果比较的两个对象是同一个对象,返回 true
        if(this == obj) {
            return true;
        }

        // 如果 obj 是 Person 类的实例对象
        if(obj instanceof Person){
            // 向下转型,因为需要用到 Person 中的属性
            Person p = (Person)obj;
            return this.name.equals(p.name) && this.age == p.age && this.gender == p.gender;
        }

        // 如果不是 Person 类实例对象,直接返回 false
        return false;
    }
}

hashCode 方法

  • hashCode 方法能提高具有哈希结构的容器的效率
  • 如果两个对象引用,指向的是同一个对象,则哈希值肯定是一样的
  • 如果两个对象引用,指向的是不同对象,一般情况下哈希值是不一样的(如果一样就是发生了碰撞)
  • 哈希值主要是根据地址号来得到的,但是 java 是在虚拟机上运行的,不能得到真实的物理地址,所以不能完全将哈希值等价于地址
public class Test {
    public static void main(String[] args) {
        AA a1 = new AA();
        AA a2 = new AA();
        AA a3 = a1;

        // a1 和 a2 指向不同对象,所以哈希值不同
        // a1 和 a3 指向相同对象,所以哈希值相同
        System.out.println(a1.hashCode()); // 1763847188
        System.out.println(a2.hashCode()); // 1617791695
        System.out.println(a3.hashCode()); // 1763847188
    }
}

class AA {}

toString 方法

基本介绍

调用 toString 方法默认会返回:全类名(包名 + 类名)+ @ + 哈希值的十六进制,子类往往会重写 Object 中的 toString 方法,用于返回对象的属性信息。打印对象或拼接对象时,都会自动调用该对象的  toString 形式。 Object 类中的 toString 方法源码如下:

// Object 中的 toString 方法

    public String toString(){

        return getClass().getName() + '@' + Integer.toHexString(hashCode());

    }

重写 toString 方法

public class Test {
    public static void main(String[] args) {
        Person p = new Person("zs", 18, '男');

        // 重写 toString 前,调用 toString 方法默认会返回:全类名(包名 + 类名)+ @ + 哈希值的十六进制
        // 当前文件不在包下,所以没有打印包名
        System.out.println(p.toString()); // Person@69222c14
        // 打印对象或拼接对象时,都会自动调用该对象的  toString 形式
        // 直接打印 p 对象和 p.toString 等价
        System.out.println(p); // Person@69222c14

        // 重写 toString 方法后
        System.out.println(p.toString()); // name=zs age=18 gender=男
    }
}

class Person {
    private String name;
    private int age;
    private char gender;

    public Person(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    // .... 省略属性的 get 和 set 方法

    // 重写 Object 中的 toString 方法
    // 子类往往会重写 Object 中的 toString 方法,用于返回对象的属性信息。
    public  String toString(){
        return "name=" + name + " age=" + age + " gender=" + gender;
    }
}

finalize 方法

  • 当对象被回收时,系统自动调用该对象的 finalize 方法。子类可以重写该方法,做一些释放资源的操作

  • 对象被回收的时机:当某个对象没有任何引用时,则 JVM 就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用 finalize 方法

  • 垃圾回收机制的调用,是由系统来决定,也可以通过 System.gc() 主动触发垃圾回收机制

class Finalize {
    public static void main(String[] args) {
        Car car = new Car("玛莎拉蒂");

        /*
         * 把 car 置空后, new Car("玛莎拉蒂") 出来的对象就没有被引用,成为了一个垃圾
         * 垃圾回收机制会根据回收算法对该对象进行销毁,在销毁前会对调用 finalize 方法
         * 由于系统是根据算法进行回收的,所以当某个对象成为垃圾后,系统不会马上进行回收
         * 可以调用 System.gc() 方法主动触发垃圾回收机制,执行该方法后不会进行阻塞,而是会继续往下执行代码
         * 调用 System.gc() 方法后不一定能百分百成功回收对象,还要受系统等因素影响
         * 如果程序员有自己的需求,可以重写 finalize 方法,在方法里实现自己的业务逻辑
         * 如果不重写,就会自动调用 Object 中的 finalize 方法,即默认处理
         */
        car = null;

        /*
         * 执行 System.gc() 方法后不会进行阻塞,而是会继续往下执行代码
         * 输出:
         * 代码执行完毕...
         * 销毁 玛莎拉蒂 对象
         */
        System.gc();

        System.out.println("代码执行完毕...");

    }
}
class Car {
    public String name;

    public Car(String name){
        this.name = name;
    }

    // 重写 finalize 方法
    protected void finalize() throws Throwable {
        System.out.println("销毁 玛莎拉蒂 对象");
        // 执行其他业务逻辑...
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值