深入解析字符串的“==“比较原理

字符串的比较

谈到字符串的比较,我不得不介绍equals方法

如果我们用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中是如何创建的:

字符串的"=="比较

首先先介绍一下字符串的存储

形如"hello"这种叫做常量字符串
1.常量字符串定义后不能更改
2.这种常量字符串储存在堆区中字符串常量池中

情况1:

public  class Stringlei {
    public static void main(String[] args) {
        String str1="hello";
        //str1为引用类型 储存了hello字符串的地址
         String str2 = new String("hello");
        String str3 = new String("hello").intern();
        System.out.println(str1 == str2);//false
        System.out.println(str1 == str3);//true
        str2.intern();
        System.out.println(str2 == str1);//false
        
    }
}

在这里插入图片描述
上图可以看出:
1.由于str1是直接被"hello"字符串赋值的,所以str1直接指向字符串常量池

2.str2是在堆区new了一个”hello“,所以在堆区开辟了一个val间接指向已经存在的"hello"字符串

3.str3用了inter()方法并且赋值给str3,就会将池中的引用给引用变量

4.可以看到最后str2.intern()后并没有与str1相等是因为并没有赋值,并且池中就有**"hello"字符串**,所以这种情况并不入池,所以str2并没有改变

情况二:

public  class Stringlei {
    public static void main(String[] args) {
        String str2=new String("he")+new String("llo");
        str2.intern();//intern并未赋值
        String str1="hello";
        System.out.println(str1==str2);//true
    	    }
        }

在这里插入图片描述

可以看到在这种情况下str1竟然等于了str2,那这又是为什么呢?

首先在堆区开辟指向字符串常量池中"he",“llo”(同时将二者放入字符串池)的空间

然后在堆区开辟字符串“hello”,其地址给str2,然后此时池中并没有"hello",让str2.intern()后,就会把**"hello"的引用入池,最后把池中的引用给str1**

可以总结出intern()方法特点:
如果方法没赋值:
1.池中没有该字符串
把引用入池
2.池中有该字符串
则不入池
如果方法赋值
常量池有就会把引用给这个变量

情况三:

public  class Stringlei {
    public static void main(String[] args) {
        String str1="hello";
        String str2 = "he"+"llo";
        System.out.println(str1==str2);//true


        String str3 = "he"+new String("llo");
        System.out.println(str1==str3);//false

    }
}

在这里插入图片描述

1.由于str2由两个常量字符串拼接而成,在编译过程中自动转化成"hello",所以str2等于str1

2.而str3是先在堆区开辟指向字符串常量池中"llo"的空间,将其与池中"he"拼接成新的字符串在堆区重新开辟,并把地址给str3

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值