java ==与equals的区别(一)

java ==与equals的区别

首先上一段代码进行分析:

public class test20210122_001 {
    
    public static void main(String[] args) {
        int a1=1;
        int a2=1;
        Integer a3=1;
        Integer a4=1;
        Integer b1 =new Integer (1);
        Integer b2 =new Integer (1);

        String s1 = "hello";
        String s2 = "hello";
        String s3 = new String("hello");
        String s4 = new String("hello");

        System.out.println(a1 == a2);   // true
        System.out.println(a1 == a3);   // true
        System.out.println(a3 == a4);   // true
        System.out.println(a3 == b1);   // false
        System.out.println(a1 == b1);   // true
        System.out.println(a1 == b2);   // true
        System.out.println(b1 == b2);   // false
        System.out.println("-------------------------");
        System.out.println(s1 == s2);   // true
        System.out.println(s1 == s3);   // false
        System.out.println(s1 == s4);   // false
        System.out.println(s3 == s4);   // false

    }

}
public class test20210122_002 {

    public static void main(String[] args) {
        objPoolTest();
    }

    public static void objPoolTest() {
        int i = 40;
        int i0 = 40;
        Integer i1 = 40;
        Integer i2 = 40;
        Integer i3 = 0;
        Integer i4 = new Integer(40);
        Integer i5 = new Integer(40);
        Integer i6 = new Integer(0);
        Double d1=1.0;
        Double d2=1.0;

        System.out.println("i==i0\t" + (i == i0));  //true
        System.out.println("i==i1\t" + (i == i1));  //true
        System.out.println("i==i2\t" + (i == i2));  //true
        System.out.println("i==i4\t" + (i == i4));  //true
        System.out.println("i==i5\t" + (i == i5));  //true
        System.out.println("i1==i2\t" + (i1 == i2));  //true
        System.out.println("i1==i4\t" + (i1 == i4));  //false
        System.out.println("i1==i5\t" + (i1 == i5));  //false
        System.out.println("i4==i5\t" + (i4 == i5));  //false
        System.out.println("d1==d2\t" + (d1==d2));  //false
        System.out.println("i1==i2+i3\t" + (i1 == i2 + i3));  //true
        System.out.println("i4==i5+i6\t" + (i4 == i5 + i6));  //true

    }
    
}

估计很多人已经感觉头晕了,下面我们来具体分析一下原因

在分析原因之前一定要先搞懂==与equals的区别:

==表示两者的内存地址是相同的,既然内存地址是相同的,那么肯定指的是同一个元素(数据/对象)

equals表示两者所指的元素相等相等不一定就是同一个元素,比如说:我有一元硬币,你也有一元硬币,我的一元硬币和你的一元硬币是相等的,但不是同一个一元硬币!

注意:==为true的两个元素equals肯定为true,equals为true的两个元素==不一定为true

public class test20210122_003 {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        if (s1 == s2)
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s2");
    }
}

输出结果为:s1 == s2

分析:首先程序会在这个String缓冲池中寻找相同值的对象,当s1="hello"时发现池中没有"hello",于是就将s1先放到了池中,所以在s2被创建的时候,程序找到了具有相同值("hello")的 s1,于是将s2也指向了s1所引用的对象"hello"。

public class test20210122_003 {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = new String("hello");

        if (s1 == s2)
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s2");

        if (s1.equals(s2))
            System.out.println("s1 equals s2");
        else
            System.out.println("s1 not equals s2");
    }
}

输出结果为:
s1 != s2
s1 equals s2

分析:首先程序会在这个String缓冲池中寻找相同值的对象,当s1="hello"时发现池中没有"hello",于是就将s1先放到了池中,但是在s2被创建的时候,程序不希望再在池里寻找旧的"hello",想在堆里面重新创建一个"hello"对象,

于是s1和s2的值虽然相同但是所指的对象却不是同一个,s1指的是池里面的"hello",s2指的是堆里面新创建的"hello"。

public class test20210122_003 {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = new String("hello");
        s2 = s2.intern();

        if (s1 == s2)
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s2");

        if (s1.equals(s2))
            System.out.println("s1 equals s2");
        else
            System.out.println("s1 not equals s2");
    }
}
输出结果为:
s1 == s2
s1 equals s2 
intern() 作用:检查字符串池里是否存在"hello"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会把"hello"添加到字符串池中,然后再返回它的引用。

也可以像下面这样操作:
String s1 = "hello";
String s2 = new String("hello").intern();
System.out.println("s1 == s2");    输出:true

针对基本数据类型和封装类型的判断:

int(Integer),char(Character),double (Double), float(Float),long(Long),short(Short),byte(Byte),boolean(Boolean)

    public static void main(String[] args) {
        int i = 40;
        int i0 = 40;
        Integer i1 = 40;
        Integer i2 = 40;
        Integer i3 = 0;
        Integer i4 = new Integer(40);
        Integer i5 = new Integer(40);
        Integer i6 = new Integer(0);
        Double d1=1.0;
        Double d2=1.0;

        System.out.println(i == i0);  //true   i和i0均是普通类型(int)的变量,所以数据直接存储在栈中,而栈有一个很重要的特性:栈中的数据可以共享。当我们定义了int i = 40;,再定义int i0 = 40;这时候会自动检查栈中是否有40这个数据,如果有,i0会直接指向i的40,不会再添加一个新的40。
        System.out.println(i == i1);  //true  返回值是true,当int和 Integer进行==比较的时候,Integer 会自动拆箱变成int,最终比较的是两者的值是否相同。

        System.out.println(i == i2);  //true
        System.out.println(i == i4);  //true
        System.out.println(i == i5);  //true

        System.out.println(i1 == i2);  //true   i1和i2均是引用类型,在栈中存储指针,因为Integer是包装类。由于Integer包装类实现了常量池技术,因此i1、i2的40均是从常量池中获取的,均指向同一个地址,因此i1=12。
        System.out.println(i1 == i4);  //false   由于i4和i5要求重新创建对象,不再重常量池里面拿旧的了,所以i4和i5指的都是新的各自独一无二的对象地址
        System.out.println(i1 == i5);  //false
        System.out.println(i4 == i5);  //false

        System.out.println(d1==d2);  //false   d1和d2均是引用类型,在栈中存储指针,因为Double是包装类。但Double包装类没有实现常量池技术,因此Doubled1=1.0;相当于Double d1=new Double(1.0);,是从堆new一个对象,d2同理。因此d1和d2存放的指针不同,指向的对象不同,所以不相等。
        System.out.println(i1 == i2 + i3);  //true   很明显这是一个加法运算,Java的数学运算都是在栈中进行的Java会自动对i1、i2进行拆箱操作转化成整型,因此i1在数值上等于i2+i3。
        System.out.println(i4 == i5 + i6);  //true

    }

重点注意:
除了double/Double类型,其他的基本类型和包装类均实现了常量池技术,
但是常量的范围是在-128,127之间的范围,如果超出了这个范围,就不能再从常量池中查找,只能在堆中创建新的了。
例如:Integer i1 = 400; Integer i2 = 400;,超过了127,无法从常量池获取常量,就要从堆中new新的Integer对象,这时i1和i2就不相等了。

==和equals一般是同类型的数据进行比较,很少用于非同类型数据之间的比较,equals一般应用同类型的对象之间进行比较,不能用于基本数据类型的比较。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值