java基础中==,equals(),Objects.equals()详细区别与细节

本文详细介绍了Java中`==`、`equals()`和`Objects.equals()`的区别。`==`用于基本类型比较值,引用类型比较内存地址;字符串比较时,相同内容的字符串在常量池中可能有相同的引用;对于包装器类型,`Integer`在一定范围内会缓存对象,导致相同值的`Integer`引用可能相同。`equals()`默认比较对象地址,`String`和`Integer`重写了该方法比较值。`Objects.equals()`提供防空判断,避免空指针异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java中==的含义

==的基本解释

==是二元运算符,其最终的结果返回的是基本数据类型中的boolean型。它是比较基本数据类型和引用数据类型,它的作用是比较两个变量是否相等,但对相等的定义我们应该达成一致。

情况一,基本数据类型之间比较

byte,short,char,int,long,float,double,boolean 他们之间的比较,比较的是他们的值。在比较它们值时,可能存在变量类型不同,在两个基本数据类型变量一致时,比较的是值。在比较两个基本数据类型不同是,会进行自动类型转换,小类型会转换成大类型,此时比较的也是值,当无法进行自动类型转换,便会报语法错误。
从本质来讲,基本数据类型比较的是内存地址,因为有jvm的常量池,所以我们赋值的是常量的内存地址。我们仅仅可以假想它们比较的是"值",但实质上是因为它们指向了同样的内存地址

情况二,引用数据类型之间比较

引用数据类型是指对象、数组、字符串等之间的比较,比较的是它们的内存地址。

字符串比较
	String s1 = "abs";
    String s2 = "abs"; //
    String s3 = new String("abs");
    System.out.println(s1 == s2);//s1与s2 内存地址相同
    System.out.println(s2 == s3);//s2与s3 内存地址不相同

在编译时s1和s2的字符串"abs"会被放入jvm的常量池中。所以s1和s2在赋值的时候都是一样指向常量池中"abs"的内存地址。而s3不同,s3新new String对象,其字符串内容被放在heap中,s3在stack中指向heap地址。因此s2和s3内存地址不同。

情况三、基本数据类型与包装器类型的比较

包装器类型是指基本数据类型对应的类(int、Integer)。在比较时,会进行自动拆箱、装箱的操作。

自动拆箱、装箱
//自动装箱
Integer a = 127; //实际上是 Integer.valueOf(127)
//自动拆箱
int b = a;//实际上是 a.intValue()

装箱就是包装成对象;拆箱就是拆为基本数据类型。这些操作就是调用预先设计好的方法。

Integer比较细节
Integer i1 = 1;//装箱
Integer i2 = 1;//装箱
Integer i3 = new Integer(1);
Integer i4 = 128;
Integer i5 = 128;
System.out.println(i1 == i2);//true
System.out.println(i4 == i5);//false
System.out.println(i2 == i3);//false
System.out.println(1 == i1);//true,拆箱

i1、i2变量都进行了装箱操作,即调用了Integer.valueof()方法。但是我们看看方法的细节

 public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
 ...chche关键代码
 	cache[k] = new Integer(j++);

其中使用了IntegerCahce进行了缓存。预先初始化了256个数组。这意味着当值在-128到127闭区间的时候,使用的是相同内存地址的Integer对象。但是这样注意,这里尽管是缓存,但它还是对象!
因此由于缓存的关系,i1与i2内存地址相同。
i4与i5由于超过了缓存,所以内存地址不同。
i2和i3,因为一个是缓存中产生,一个是新new的对象,所以内存地址不同。
1和i1,从结果来看,i1拆箱了,即i1与1比较是,比较的不在是i1对象的内存地址,而是现将i1拆箱i1.intValue(),返回了i1对应的jvm中常量池的地址。所以i1和1的内存地址在==比较时是相等的。
同理的Short、Long类也有类似的操作。我们只需要正确理解内存地址、拆装箱的操作即可。

java中obj.equals()含义

==其实是java给我们定义的两个变量相等的含义,即内存地址是否相等。但这显然无法满足我们的需求。因此有了equals方法的定义。
equals方法是所有对象都拥有的默认方法。使用时我们必须明确的了解对应对象的equals具体实现。当然常用的String、Integer已经实现好了。

Integer equals解释

 public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
}

这个相等很简单,类型是否相同,其次对应的数字值是否相同。
关于 i4.equals(128),这将返回true,因为128会被装箱为Integer类型。但是i4.equals(new Long(128)),这将放回false,因为类型不同。

String equals解释

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

先比较地址,其次比较字符串值。

java中Objects.equals()含义

这是工具类。


 public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

先比较内存地址,其次用equals比较,这里方便地方就是防止NPE(NullPointerException)的发生。
这里我说一下一个细节,关于是否使用Objects.equals方法来判断相等它有个很方便的功能就是永远不会发生NPE,但是在某种情况下代码吞掉NLP可能会引发致命的问题.关于如何思考NPE问题及解决办法将在其他文章中总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值