Java String.intern() 函数 new string

Java String.intern() 函数 new string,第1张

intern简介

首先判断常量池中是否存在这个字符串,存在则直接返回常量池中的地址。若不存在,先把它放入常量池中,再返回该地址。
比如(”a“+“b”).intern=="ab"永远为true

接下来用一个个例子解释new string() ,”a“, + 的底层原理。

1、字符串s指向常量池中”ab“的引用,因为"a""b"都是字面量,并且编译器直接优化成s="ab"

String s="a"+"b";

2、字符串s指向堆中”ab“对象,因为ab都是堆对象的引用,a+b本质使用Stringbuilder.append进行拼接。

String a=new String("a");
String a=new String("b");
String s=a+b;

3、字符串s指向常量池中"ab"的引用,因为ab本质是常量,跟上面同理

final String a=new String("a");
final String a=new String("b");
String s=a+b;
面试题

1、对于String s=new String("a")会创建两个对象?

会创建2个对象,一个字符串常量池中“a”对象,一个是堆中的"a’对象

2、对于String s=new String("a")+new String("b")又会创建几个对象?
会创建6个对象!
原理:上一题分析可知new String(“a”)产生2个对象,同理new String(“a”)也产生2个对象,由于+号两边只要有变量,就会使用产生一个stringbuilder对象,最终builder转为String调用toString方法,本质是new String(“ab”)再产生一个对象。

jdk78的intern方法

会让常量池指向堆的引用,节省空间。而jdk1.6是直接把堆中的对象拷贝一份。

下面再用几个例子加深对intern函数的理解。

    @Test
    public void test4() {
        String s3=new String("a")+new String("a");
        s3.intern(); // 常量池中创建aa,并指向堆中的s3
        String s4="aa";
        System.out.println(s3==s4); // jdk78 true

        String s5=new String("b"); // 堆
        String s6="b"; // 常量池
        String s7=s5.intern(); // 常量池
        System.out.println(s5);
        System.out.println(s5==s6); // false
        System.out.println(s5==s7); // false
        System.out.println(s6==s7); // true
    }

    @Test
    public void test3() {
        String str1=new String("hello"+"world");
        String intern = str1.intern(); // 返回常量池地址,但该地址是指向堆中的str1
        String str2="helloworld"; // 返回常量池地址
        System.out.println(str1==intern); // false
        System.out.println(str2==intern); // true
    }

    @Test
    public void test2() {
        String str1=new String("hello"+"world"); // 堆 同时在方法区常量池生成helloworld,都是常量不会使用stringBuilder
        String str1_intern=str1.intern(); // 常量池 直接返回常量池中的helloworld,因为上一个语句已将helloworld放入常量池
        String str2="hello"+"world"; // 常量池
        String word="word";
        String str3=new String("hello"+word); // 堆 有一个是变量就是用builder,因为编译时不知道变量的具体值
        System.out.println(str1==str2); // false 因为str1指向堆,str2指向常量池
        System.out.println(str1==str1_intern); // false str1_intern返回的常量池的地址
        System.out.println(str2==str1_intern); // true
        System.out.println(str1==str3); // false 两个是不同的普通的堆对象
    }

    @Test
    public void test1(){
        String str1="hello"; // 指向常量池
        String str2=new String("hello"); // 指向堆中的地址,但实际引用的是堆中的字符串常量池地址
        String str3=str2.intern(); // 指向常量池
        System.out.println(str1==str2); // false
        System.out.println(str1==str3); // true
        System.out.println(str2==str3); // false
    }

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/917571.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存