Java的Object类

概述:所有类的根类(父类),所有的类都会直接或者间接继承Object类

Object中的toString()方法:

如果不重写这个toString方法:默认形式是:

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

这个我们可以进到Object里面去看

 


a.如果没有重写Object中的toString方法,直接输出对象名会默认调用Object中的toString方法,直接输出地址值 

这两行代码生成的结果是一样的

 b.如果重写了Object中的toString方法,再输出地址值,重写没有意义,所以重写完toString之后,应该返回对象的内容 

然后我们按住ctrl 鼠标点击list的toString方法追踪一下

可以得出这里重写了这个toString()方法。

对这个JavaBean对象重写toString方法之后也是一样

Object的equals方法:

这部分的介绍我直接通过代码的案例来讲:

第一个案例:

class A {

    String name;
    int age;



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

public class Test {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new A();
        System.out.println(a1==a2);
        System.out.println(a1.equals(a2));
    }
}

第一段代码:我创建了一个A对象,我并没有重写equals方法,所以我们也可以知道,如果我在主函数中调用,那应该调用Object的默认equals方法

输出结果:

false
false

这是应该Object的默认equals方法比较得是地址值

第二个案例:

public class Test {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new A();
        System.out.println(a1==a2);
        System.out.println(a1.equals(a2));

        System.out.println("========================");

        String a = "abc";
        String b = "abc";
        System.out.println(a==b);
        System.out.println(a.equals(b));
    }
}

class A {

    String name;
    int age;



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

 这一段代码我又创建了两个String变量:值都是"abc"

输出结果:

true

true

a==b 最后能输出true的原因是:

在Java中,当你声明两个字符串变量 ab 并初始化为相同的值 "abc" 时,System.out.println(a==b) 会输出 true。这是因为在Java中,字符串常量池(String Pool)的概念起了作用。

字符串常量池是一个特殊的内存区域,用于存储所有创建的字符串实例。当你创建一个新字符串 "abc" 时,实际上系统会在字符串常量池中查找是否有相同内容的字符串,如果找到了,就直接引用那个已经在池中的对象,而不是新建一个新的对象。所以,"abc""abc" 实际上指向的是同一个内存地址,因此 == 运算符比较它们的时候返回 true,表示它们是相等的。

 a.equals(b)最后能输出true的原因是:String重写了equals方法,在重写的方法中比较了两个字符串的序列


所以我们可以先做一个小总结:

  a.如果没有重写Object中的equals方法,那么就会调用Object中的equals方法,比较对象的地址值
  b.如果重写了Object中的equals方法,那么就会调用重写后的equals方法,应该比较对象的内容

接着我们再从idea自动给我们重写的equals方法的几行代码中分析一下逻辑:

 

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

这一段是编辑器自动帮我们写的equals方法

首先先说明一下,这里面的this是什么,在Java面向对象的特性中有一个this

Java面向对象特性-CSDN博客

这里的this是指当前对象,也就是调用这个方法的对象:

比如:a.equals(b),那这里的a就是当前对象,也就是这个this,b就是Object o 的o 

this == o 这个的作用是判断如果比较的对象和当前对象一致的话,就不需要再比了,直接返回true

o == null 这个的作用是判断传入的对象是否为空,为空直接短路后面的判断,直接返回false

getClass() != o.getClass()这个就比较复制,需要展开来说了

看这一段代码,我试图去将A的属性中的age和name和当前对象进行比较,结果发现直接爆红

这是为什么?

因为age和name是子类(这里的子类相对的父类就是Object),父类不能调用子类私有属性

OK,写道这里肯定会有人说,向下转型就行了。

结果肯定是可以的

不过我们再来看:

 如果我们在外面传了一个list集合,那这样还能判断出来嘛

答案肯定是不能,应该是会报转换类型错误的报错java.lang.ClassCastException

解决办法是什么呢?

就是在向下转型的时候用instanceof关键字判断一下。

所以等我们把上面这些判断都明白了,自然就明白了代码自动给我们生成的getClass() != o.getClass()这段代码。

最后,我们再来说一下 "==" 和 equals的区别

在Java中,==.equals()是两个用于比较的对象运算符,但它们在用途和用法上有所不同:

  1. == 运算符:

    • 用于比较基本数据类型(如int、char等)或引用类型的变量是否指向同一内存地址。
    • 当比较对象时,它检查的是两个对象的引用是否完全相同,即它们在内存中的位置是否一样。
    • 对于字符串和数组,如果两个对象的引用相等,则==返回true,即使它们的内容相同。
  2. .equals() 方法:

    • 这是一个方法,通常由Object类定义,并在所有类中继承,包括String、Integer等引用类型。
    • 对于自定义类的对象,.equals()方法可以根据类的设计意图来判断两个对象的内容是否相等。
    • 在String类中,.equals()默认比较的是字符串的实际内容;而在其他可变类型如ArrayList,通常重写为比较元素内容而非引用。

总结来说,==主要用于直接比较对象的地址,而.equals()则是用来比较对象的内容是否相等。如果你想要比较两个对象的数据值而不是它们的引用,应该使用.equals(),除非你知道你在比较的是不可变类型(比如基本类型或String),在这种情况下,==就足够了。

  • 29
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值