经典面试题1-String常量池

经典面试题1-java中String字符串常量池

题目:写出以下程序的输出结果(环境,jdk1.8)

public static void main(String[] args) {
    String s1 = new StringBuilder("ja").append("va").toString();
    String intern1 = s1.intern();
    System.out.println(s1 == intern1);
    String s2 = new StringBuilder("bei").append("jing").toString();
    String intern2 = s2.intern();
    System.out.println(s2 == intern2);
    String s3 = new StringBuilder("1.8.0").append("_231").toString();
    String intern3 = s3.intern();
    System.out.println(s3 == intern3);
    System.out.println("----------------------------------------");
    String s4 = new String("hello") + new String("hello");
    String s5 = "hellohello";
    String intern4 = s4.intern();
    System.out.println(s4 == s5);
    System.out.println(s4 == intern4);
    System.out.println(s5 == intern4);
    String s6 = new String("hi") + new String("hi");
    String intern6 = s6.intern();
    String s7 = "hihi";
    System.out.println(s6 == intern6);
    System.out.println(s6 == s7);
    System.out.println(intern6 == s7);
    System.out.println("----------------------------------------");
    String s8 = "ni" + "hao" + "ni";
    String s9 = new String("ni") + new String("haoni");
    String intern9 = s9.intern();
    System.out.println(s9 == intern9);
}

解析

环境是jdk1.8!!!字符串入常量池的规则

1、第一次以字面字符串(一个或多个字面字符串拼接)形式出现,直接进入常量池

​ 例如:

​ String s5 = “hellohello”;

​ String s8 = “ni” + “hao” + “ni”;
注:s8会在编译时常量折叠,编译器会优化成String s8 = “nihaoni”;

2、常量池中没有,堆(一般的堆的概念)中有,用intern()方法加入到常量池中,会直接在常量池中引用该堆中字符串的地址(这点jdk1.6和jdk1.7(1.8)是不同的,jdk1.6相当于是常量池中第一次出现了这个字符串,不与堆中的关联)

​ 注:

​ intern()方法返回的是常量池中那个字符串的地址,常量池中之前如果存在,则返回的就是存在的那个字符串的地址。

3、常量池中已经有了,再次以字面字符串出现或使用intern()方法出现时,都是引用的常量池中已经有的地址

​ 注:

​ 常量池中的字符串(jdk1.7(1.8))会存在几种情况:1、与堆中某个字符串地址关联,2、不与堆中字符串地址关联

结果

false:s1表示的字符串是java,但是java这个字符串在常量池不是第一次出现,系统加载的时候加载了一些字符串,所以intern1的地址是之前存在的java字符串的地址,而不是s1的地址
true:s2表示的字符串是beijing,在常量池第一次出现,所以intern2引用的是s2的地址
false:与第一个相同,jdk版本是1.8.0_231,这个字符串也在常量池存在了
----------------------------------------
false:s4在堆,s5在常量池,s5表示的字符串是第一次在常量池出现
false:intern4引用的是s5的地址,不是s4的地址
true:intern4引用的是s5的地址
true:s6在堆,intern6在常量池,intern6表示的字符串是第一次在常量池出现,引用的是s6的地址
true:s7表示的字符串不是第一次在常量池出现,引用之前出现的地址(intern6的地址),也就是s6的地址
true:s6、intern6、s7用的都是s6的地址
----------------------------------------
false:intern9引用的是s8的地址,不是s9的,与第一个是相同的场景

补充

“java”字符串第一次出现的地方:sun.misc.Version

package sun.misc;
import java.io.PrintStream;
public class Version {
    private static final String launcher_name = "java";
    private static final String java_version = "1.8.0_231";
    private static final String java_runtime_name = "Java(TM) SE Runtime Environment";
    private static final String java_profile_name = "";
    private static final String java_runtime_version = "1.8.0_231-b11";
    private static boolean versionsInitialized;
    private static int jvm_major_version;
    private static int jvm_minor_version;
    private static int jvm_micro_version;
    private static int jvm_update_version;
    private static int jvm_build_number;
    private static String jvm_special_version;
    private static int jdk_major_version;
    private static int jdk_minor_version;
    private static int jdk_micro_version;
    private static int jdk_update_version;
    private static int jdk_build_number;
    private static String jdk_special_version;
    private static boolean jvmVersionInfoAvailable;
    ...
}

参考

1、https://www.cnblogs.com/tongkey/p/8587060.html

2、《深入理解Java虚拟机》(还没看过)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值