Java基础:String之相等(==)

public class String {
    public static void main(String[] args) {
        //==比较的是两方存放的对象的内存地址,equals比较的是内容是否相等
        String a = "hello2";
        final String b = "hello";//因为是final,最先被初始化
        String d = "hello";
        String c = b + 2;
        String e = d + 2;
        System.out.println(a == c);//true,变量a和c在初始化的时候,都等于hello2,所以被认定为指向同一个地址,所以两个变量在比较地址的时候,地址相等。
        System.out.println(e == a);//false,变量e在初始化的时候,指向地址不为hello,也不为hello2,而是“"hello"+2”的地址,所以这个地址与hello2,与hello都不同
        System.out.println(e == d);//false
        System.out.println(b == d);//true,变量d的地址被认定为指向final变量b的地址
        System.out.println(a .equals(e) );//true,内容相同
        //a,b,c,d,e,都存储在栈中,先从常量池中查找是否有“”中的字符串,如果有,直接引用,如果没有,先在常量池中创建这个字符串,再引用其地址回到栈中
        //
        String s1="abc";
        String s2="abc";
        System.out.println(s1 == s2);//true,s1和s2初始化的时候,被指定为同一个地址
        s1=s1+"a";
        System.out.println(s1 == s2);//false,当s1变化的时候,s1的指向的地址发生变化
        s2=s2+"a";
        System.out.println(s1 == s2);//false,当s2发生与s1相同变化的时候,s1和s2指向的地址仍然不同
        //
        String s3 = new String("xyz");
        String s4 = new String("xyz");
        System.out.println(s3 == s4);//false
        //s3,s4都存储在栈中,但是会在堆中创建new String(“xyz”)对象,new String再去常量池中进行拷贝,所以s3和s4的判断地址相等的时候,是不会相等的
    }
}

 


        String s1 = new String("1") + new String("1");
        String s2 = s1.intern();
        String s3 = "11";
        System.out.println(s3 == s1);
        System.out.println(s3 == s2);
        System.out.println(s1 == s2);
        String s6 = new String("go") +new String("od");
        String s7 = s6.intern();
        String s8 = "good";
        //s6=s6+1;只增加这一行,下面运行结果为:false,true,false
        //s8=s8+1;增加两个,下面运行结果为:false,false,false
        System.out.println(s6 == s7);
        System.out.println(s7 == s8);
        System.out.println(s6 == s8);
        //s1在初始化的时候,在栈里面存储一个s1,在堆里面存储一个new String+new String,所以常量池里面只有一个1
        //s2在初始化的时候,使用s1.intern(),
        //关于intern方法,源码里的解释为:当调用 intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(oject)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用
        //意思就是s2在初始化的时候使用intern,那么就会在常量池中将s1对象加入到常量池中,所以常量池中的"11"的地址其实就是s1“当前”的地址,也就是说s2实际上指向了s1“当前”的地址
        //那么s3在初始化的时候,在常量池找到的也是s1“当前”的地址,所以这个时候进行地址比较的时候,因为s2和s3引用的地址都是s1的,所以会相等
        //s6,s7,s8也是一样的,s7使用intern以后,将"good"存入了常量池,s7,s8都指向的是当前的s6的地址。如果后续对s1,s2,s3,s6,s7,s8有更改的话,那么相应的地址也就会发生变化,但是常量池里的地址是不会变的。

 


引用一个图片帮助理解:

String str1="abc";
String str2="abc";
String str3="abc";
String str4=new String("abc");
String str5=new String("abc");


        String s1="hello";
        String s2=s1;
        System.out.println(s1==s2);//true
        s1=s1+1;
        System.out.println(s2=="hello");//true
        //这个例子表明了一个问题,s1的地址是可以变化的,而常量的地址是不变的。

总结:String这个引用类型的道道还是有不少的,一不注意可能就会发生奇奇怪怪的问题。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值