一文弄懂String常量池,String常见面试题,以及intern()不同jdk的区别

前言

本次代码使用 jdk 1.8版本,并且以下代码示例除了第一个写了main()方法,并且所有的示例分别独立运行 ,其余为了简洁做了缺省main()。在创建字符串分析的同时,都默认省略了栈中的句柄指向分析。进入正题之时,先科普几个知识点

  • String源码里面标注为final修饰的类,是一个不可改变的对象,那平时用到字符串A+字符串B怎么改变了呢,其实这里有涉及到String的常量池,首先常量池存放在方法区
  • 在jdk1.6时,方法区是存放在永久代(java堆的一部分,例如新生代,老年代)而在jdk1.7以后将字符串常量池移动到了的堆内存中
  • 在jdk1.8时,HotspotVM正式宣告了移除永久代,取而代之的是元数据区,元数据区存放在内存里面(存放一些加载class的信息),但是常量池还是和jdk1.7存放位置一样还是存放在堆中。

一、常见的面试题

public static void main(String[] args){
    
    
        String s1 = new String("123");
        String s2 = "123";
        System.out.println(s1 == s2);
}

基本上大家都能知道是false,但是再这么深究一次,问 String s1 = new String(“123”) 创建了几个对象,String s2 = “123” 创建 了几个对象,那如果题目稍微改变一下成下面这样,那输出的又是什么?

 String s1 = new String("123").intern();
 String s2 = "123";
 System.out.println(s1 == s2);  // true
 
 // 如果这样再改一下 
 String s1 = new String("123");
 s1.intern();
 String s2 = "123";
 System.out.println(s1 == s2);  // false

如果对输出结果不是很明白的,本文都会一一解答并且进行拓展。

一、创建字符串分析:

首先要分析String,一定要知道String几种常见的创建字符串的方式,以及每一种不同的方式常量池和堆分别是什么储存情况。

1.直接写双引号常量来创建
判断这个常量是否存在于常量池,
  如果存在,则直接返回地址值(只不过地址值分为两种情况,1是堆中的引用,2是本身常量池的地址)
    如果是引用,返回引用地址指向的堆空间对象地址值
    如果是常量,则直接返回常量池常量的地址值,
  如果不存在,
    在常量池中创建该常量,并返回此常量的地址值

String  s = "123";
//true,因为s已经在常量池里面了,s.intern()返回的也是常量池的地址,两者地址一样为true
System.out.println(s == s.intern());

在这里插入图片描述

转自:https://blog.csdn.net/xzjayx/article/details/103020029?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&dist_request_id=9e66ef09-8558-4e27-8909-50f68c0d45e9&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control

猜你喜欢

转载自blog.csdn.net/weixin_42754971/article/details/113912161