String解析——String s=new String("a");String s = "a" + "b";String的intern方法等问题

我们经常能看到一些问题,比如String字符串创建了几个对象,判断是否相等,等等。在这里做一个总结。

String字符串在内存中的存储

我们常把java内存区分为“堆”和“栈”,但实际上其内存结构用下图来描述更准确:
这里写图片描述
其中方法区存储虚拟机加载的类信息,常量,静态变量,编译后的代码等数据。运行时常量池是方法区的一部分,我们接下来要说的字符串就保存在常量池中。在java中,所有的字符串都是常量,即每一个不同的字符串都会在常量池中创建一条数据。

示例

简单了解了上述知识,我们来看如下几个例子:

  1. String s=new String(“a”)创建了几个对象?
    两个对象,一个是“a”对象,在常量池中创建;一个是new关键字在堆中创建的“a”的拷贝对象,s指向拷贝对象。

  2. String s = “a” + “b” + “c”创建了几个对象?
    一个,因为”a”“b”“c”都是常量,在编译的时候直接存储其字面值,相当于“abc”。

  3. 判断下列字符串是否相等

    String str1 = "a";
    String str2 = "b";
    String str3 = "ab";
    String str4 = "a" + "b";
    String str5 = str1 + str2;
    String str6 = new String("ab");
    
    System.out.println(str3.equals(str6));
    System.out.println(str3 == str6);
    System.out.println(str3 == str4);
    System.out.println(str4 == str5);
    System.out.println((str1+str2) == str5);

    返回的结果是:
    true
    false
    true
    false
    false
    前两个很好理解;第三个返回true是的原因见上题;
    第四个为什么返回false,str4的值在编译期可以确定,所以直接指向“ab”。字符串相加的时候,如果其中含有变量,则在编译期无法确定其值,所以不会指向“ab”。我们知道“==”是判断地址是否相同,所以结果是false。如果我们将str1与str2声明为final类型,则结果是true。
    第五个返回false,是因为虽然同为变量赋值,但是相当于创建了两个不同的对象。

  4. 关于String中的intern方法

    • public String intern()
      返回字符串对象的规范化表示形式。
      一个初始时为空的字符串池,它由类 String 私有地维护。
      当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。
      它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。
      所有字面值字符串和字符串赋值常量表达式都是内部的。

      返回:
      一个字符串,内容与此字符串相同,但它保证来自字符串池中。

    String str = "java";
    String str1 = new StringBuilder("中国").append("钓鱼岛").toString();
    String str2 = new StringBuilder("ja").append("va").toString();
    System.out.println(str1.intern() == str1);
    System.out.println(str2.intern() == str2);

    返回的结果在JDK1.6中是两个false,在JDK1.7中是true和false。为什么不一样呢?
    在JDK1.6中,intern()方法会把首次遇到的字符串实例复制到常量池中,返回的也是常量池中这个字符串实例的引用,所以str1的引用于str1.intern()的引用不同。在JDK1.7中,intern()的实现不会再复制实例,只是在常量池中记录首次出现的实例引用,而其实际对象保存在堆中,所以str1的引用与str1.intern()的引用相同。str2返回false是因为“java”这个引用在之前出现过,不符合“首次原则”。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值