java中==判断你需要知道的 | 青训营笔记

124 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第11天。

昨天写一些java基础笔记的时候,碰到了一些很基础但是比较有趣的一些东西,java中‘==’ 的判断和String的一些特殊的东西,这里浅浅记录一下。

如果有兴趣,可以看看我之前的文章:红包算法之如何助你抢到大红包 | 青训营笔记 - 掘金 (juejin.cn),哈哈推广一波。

Java ‘==’ 如何判断

Integer 和 int 的 ==

首先我们看下如下代码:

    Integer i1 = 127;
    Integer i2 = 127;
    Integer i3 = 128;
    Integer i4 = 128;
    int i5 = 128;
    int i6 = 128;
    System.out.println(i1 == i2);    // true
    System.out.println(i3 == i4);    // false
    System.out.println(i5 == i6);    // true

结果正如注释那样:

    true
    false
    true

这里其实更多的实验可以证明如下两条:

  • int不管怎么比,只要值相同,那么 == 结果一定为true
  • Integer在 -128~127 之间,值相同,那么 == 结果为true,超过这个区间,值相同与否,== 结果必为 false

那这是为什么呢?

封装类

  • 封装类:也叫包装类。为了能将基本类型转化为对象进行处理,并能连接相关的方法。
  • Java为每个基本数据类型都提供了包装类,这样便可以把这些基本类型转换为对象来进行处理了。
  • 需要说明的是,Java是可以直接处理基本数据类型的,但在有些情况下需要将其作为对象来处理,这时就需要将其转换为包装类了。
  • 八种包装类(对象不分大小):除了char对应Character,int对应Integer,其他的包装类都是把基本数据类型的首字母大写。

这也就是说,Integer a = 1 其实相当于 Integer a = new Integer(1)

Java中 == 和 Integer

  • 如果是基本数据类型,则 == 比较的是值;如果是对象类型,则 == 比较的是对象的地址

所以这就是为什么对于int,只要值相同,那么就是true

而对于类,比如说double 的包装类 Double

Double d1 = 1.0;
Double d2 = 1.0;
System.out.printl(d1 == d2);      // false

但是那么为什么在-128 ~ 127 范围内,Integer又会‘判断值’呢

其实不是因为判断了值:

  • 设计时为了减少Integer对象创建的开销,提升整体效率,预先创建好了共256个Integer对象供后续使用,如果传入value数值在**-128~127范围内,那么所有在这个范围内被创建的对象(句柄)实际都指向同一个地址**,即被预创建Integer对象所在的地址。

如果我们实在想判断值,那么我们可以用equals 的方法:

  • 这里用 .equals 都是返回true的,equals的时候会先比较地址,然后再比较值

另外

对于

int a = 1;
Integer b = 1;
System.out.println(a == b);      // true

这种情况是输出 true 的,因为Integer是int的封装类,int与Integer比较时,Integer会自动拆箱,也就是相当于两个 int 类型的值比较。

String 的 == 比较

对于以下代码:

String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1 == s2); // ouput -> true
System.out.println(s1 == s3); // output->false

经过上面的学习,按理说也应该是对象的比较,那么两个应该都是false才对

那为什么s1跟s2比较为true呢,不妨看下面这些代码:

String g = "123";
String h = "123";
String i = new String("123");

System.out.println(Integer.toHexString(g.hashCode()));
System.out.println(Integer.toHexString(h.hashCode()));
System.out.println(Integer.toHexString(i.hashCode()));
System.out.println(Integer.toHexString(System.identityHashCode(g)));
System.out.println(Integer.toHexString(System.identityHashCode(h)));
System.out.println(Integer.toHexString(System.identityHashCode(i)));

想要理解输出的内容,我们要知道hashCode和identityHashCode

hashCode和identityHashCode

hashCode hashCode方法可以根据对象的内存地址算出来一个int数字,代表了该对象在内存中的存储位置。

有些类重写了hashcode,如String, 其源码如下:

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;
        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

不难看出,如果字符串值相同的话,那么hashCode值一定相同

identityHashCode

而identityHashCode是由java.lang.System类提供了一个静态方法

public static native int identityHashCode(Object x);

identityHashCode根据对象的内存地址来计算hashcode,不管对象是不是重写了hashcode方法。

String

上面一个代码,三个字符串地址输出为:

    be32
    be32
    be32
    1b6d3586
    1b6d3586
    74a14482

可以看到,字符串均为“123”,故hashCode值相同,而g和h的identityHashCode值相同,i的identityHashCode不相同,这里就涉及到:

  • 在Java中,String存在String pool,其中存放可以共享的字符串对象,在声明一个字符串对象时,会先去其中寻找是否存在相同的String内容,假设存在是不会创建新对象,故此时二者的内存地址相同。
  • 但是new String会重新开辟地址,因此与之前String对象地址不同

其在内存中相当于:

image.png

到这里,就可以解释,为什么s1 == s2结果为true了。

最后

附测试源码:


import javax.sql.DataSource;

public class Mixed {
    public static void main(String[] args) {

        AboutVariable aboutVariable = new AboutVariable();
        aboutVariable.stringTest();

    }

}

class AboutVariable{

    void test1() {

//        Integer i1 = 127;
//        Integer i2 = 127;
//        Integer i3 = 128;
//        Integer i4 = 128;
//        int i5 = 128;
//        int i6 = 128;
//        System.out.println(i1 == i2);    // true
//        System.out.println(i3 == i4);    // false
//        System.out.println(i3 == i6);    // true

        Double d1 = 1.00;
        Double d2 = 1.00;
        System.out.println(d1 == d2);
    }

    void stringTest(){

        String f = "123";
        System.out.println(Integer.toHexString(f.hashCode()));
        System.out.println(Integer.toHexString(System.identityHashCode(f)));
        f = new String("122");
        System.out.println(Integer.toHexString(f.hashCode()));
        System.out.println(Integer.toHexString(System.identityHashCode(f)));

        String g = "123";
        String h = "123";
        String i = new String("123");

        System.out.println(Integer.toHexString(g.hashCode()));
        System.out.println(Integer.toHexString(h.hashCode()));
        System.out.println(Integer.toHexString(i.hashCode()));
        System.out.println(Integer.toHexString(System.identityHashCode(g)));
        System.out.println(Integer.toHexString(System.identityHashCode(h)));
        System.out.println(Integer.toHexString(System.identityHashCode(i)));
        System.out.println(g == h);
        System.out.println(h == i);
    }
    
}

如果这篇文章对你有帮助的话,请给我点一个赞吧,你的支持就是我创作的最大动力。

如有不对之处,欢迎指出~