String—笔试判断

String-不同情况的字符串对象进行"=="比较的结果(jdk1.8)

public class Main{
    public static void main(String args[]){
        String str1 = "a";
        String str2 = "b";
        String str3 = "ab";
        String str4 = str1 + str2;
        String str5 = "a" + "b";
        
        System.out.println( str3 == str4 );//(1) false
        System.out.println( str3 == str5 );//(2) true
        System.out.println( str4 == str5 );//(3) 结合(1)(2) false
    }
}
  • 运行程序时,运行时常量池中将 “a” ,“b”,“ab” 三个字符串对象创建出来,并放入StringTable中;

通过字符串变量 str1 + str2 得到 str4 的内部逻辑是:

str1 + str2 = new StringBuilder()
    .append(str1)
    .append(str2)
    .toString();

StringBuilder中toString()方法的源码如下:

@Override
public String toString() {
    // Create a copy, don't share the array
    return new String(value, 0, count);//通过new关键字创建了对象,存在堆中
}

由源码可知, StringBuilder.toString()方法在转换的过程中是new了一个String对象的,也就是所str4 = str1 + str2 ;的过程其实是创建了新的字符串对象,通过new关键字创建的对象都存放在JVM的堆内存中[[JVM内存结构]( (1条消息) JVM—内存结构_m0_53759248的博客-CSDN博客 )] , 而str3是存放在StringTable中.

  • (1) 由以上可知,str3 == str4结果为false;
  • 在java文件编译期间,变量的值是无法确定的,而常量的值是确定的,“a”,“b”,"ab"都属于常量; 含有变量的运算在编译期间是无法做的,而只含有常量的运算是可以做的,而且运算之后的结果是固定的.{即:java在编译期间会直接计算只含有常量的运算}

“a”+“b"在编译的过程就可以计算出结果为"ab”; 之前"ab"对象已经存放在StringTable中了,所以给str5赋值的时候直接将StringTable中的"ab"对象的引用给str5即可.

  • (2)根据上面一点可以得出(2)处为true;(3)处为false

public class Main{
    public static void main(String args[]){
        String str6 = new String("a");
        String str7 = new String("b");
        String str8 = new String("ab");
        String str9 = str6 + str7;
        String str11 = "a" + "b";
    	System.out.println( str8 == str9 );//(4) false
    	System.out.println( str8 == str11 );//(5) false
    	System.out.println( str9 == str11 );//(6)  false
        System.out.println( str6 == "a" );//(7)  false
	}
}
  • 以上代码在编译期间,“a”,“b”,“ab"同样转换了字符串对象存放在StringTable中,在执行的过程中,给str6,str7,str8赋值时采用了new关键字,所以在堆中又创建了三个新的字符串对象,并将引用给了变量,此时JVM中"a”,“b”,"ab"对象都有两个,变量指向的是队中的对象.

  • str9是通过变量相加得来,内部还是通过StringBuilder.toString()创建了新的字符串对象,存放在堆中,但是str9所指向的"ab"对象在StringTable中没有.

  • 显然,代码中(4)(5)(6)(7)处的结果都为false;


使用intern()方法后的比较.

  • JDK1.7以后,String中的intern()方法作用:

手动的将某个字符串对象尝试放入StringTable中,如果有则不放入,没有则放入,最后一定会将StringTable中的该字符串对象返回.

  • JDK1.6以前,String中的intern()方法作用:

作用基本和jdk1.7是一样的,但是在StringTable中没有该对象的时候,是复制一个对象放入StringTable中,所以在堆中的对象和在StringTable中的对象本质上是两个对象。

public class Main{
    public static void main(String args[]){
        String s1 = new String("a"); //s1指向堆中的对象"a"
        String s2 = s1.intern();  //s2指向StringTable的对象"a"
        
        String s3 = new String("b");//s3此时指向堆中的对象"b"
        s3 = s3.intern();//s3此时指向StringTable的对象"b", 此时执行垃圾回收的话,堆中的对象"b"会被GC回收.
        
        System.out.println( s1 == "a" );//(1)false
        System.out.println( s2 == "a" );//(2)true
        System.out.println( s3 == "b" );//(3)true
        
        String s4 = new String("a") + new String("b");//s4此时指向堆中的对象"ab",且此时StringTable中不存在"ab"对象.
        System.out.println( s4 == "ab" );//(4)false
        System.out.println( s4.intern() == "ab" );//(5)true  此时s4.intern()将"ab"对象放入了StringTable中,s4.intern()指向StringTable,但s4仍然指向堆中的"ab"对象.
        System.out.println( s4 == s4.intern() );//(6)false
    	
	}
}

根据intern()方法的定义,结合之前的内容,就很容易得出上方的(1)(2)(3)(4)(5)(6)处的结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莽晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值