Java之String常量池【面试常考】

String常量池

配套学习资料【含授课视频、源码】:https://link3.cc/ashao

常见面试题:

​ 分析下面代码的输出结果。

public static void main(String[] args) {
    String s1 = "Hello";  
    String s2 = "Hello";  
    System.out.println(s1 == s2);  // ?

   	String s3 = new String("Hello");
    String s4 = new String("Hello");

    System.out.println(s3 == s4);  // ?
    System.out.println(s1 == s3);  // ?
}

//程序输出
true
false
false

面试题分析:

创建字符串对象,和其他对象一样,会占用计算机的资源(时间、空间)。大量且频繁的创建字符串对象,会极大地影响程序的性能。

JVM为了提高性能、减少内存开销,开辟了一个字符串常量池(类似缓存区)

String常量池:

在Java中,String常量池是一块特殊的内存区域,用于存储字符串常量。String常量池的设计目的是为了节省内存和提高性能。

当我们创建字符串常量时,如果字符串常量池中已经存在相同内容的字符串,那么新创建的字符串常量会直接引用已存在的字符串对象,而不会创建新的对象。这样可以避免重复创建相同内容的字符串,节省内存空间。

在JDK8及之后的版本中,字符串常量池的位置与其他对象的存储位置,都位于堆内存中。这样做的好处是,字符串常量池的大小可以根据需要进行调整,并且可以享受到垃圾回收器对堆内存的优化。

Java将字符串放入String常量池的方式:

  1. 直接赋值:通过直接赋值方式创建的字符串常量会被放入常量池中。

    例如:String str = "Hello";

  2. 调用String类提供intern()方法:可以将字符串对象放入常量池中,并返回常量池中的引用。

    例如:String str = new String("World").intern();

注意:通过new关键字创建的字符串对象不会放入常量池中,而是在堆内存中创建一个新的对象。只有通过直接赋值或调用intern()方法才能将字符串放入常量池中。

案例1:

package com.briup.chap07.test;

public class Test062_String {
	public static void main(String[] args) {
		String s1 = "Hello";  // 字符串常量,放入常量池
        String s2 = "Hello";  // 直接引用常量池中的字符串对象
        System.out.println(s1 == s2);  // true,引用相同
        
        // 直接new String对象,不会将'World'放入常量池
        String s3 = new String("World");
        
		// 调用intern()方法,将'World'放入常量池,并返回常量池中的引用
		String s4 = new java.lang.String("World").intern();
		
		String s5 = "World";
        
        System.out.println(s3 == s4);  // false,引用不同
        System.out.println(s4 == s5);  // true,引用相同
	}
}

对应内存图:
在这里插入图片描述

案例2:

package com.briup.chap07.test;

public class Test062_String2 {
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = "b";

        // 常量优化机制:"a" 和 "b"都是字面值常量,借助 + 连接,其结果 "ab" 也被当作常量
        String s3 = "a" + "b";
        String s4 = "ab";

        System.out.println(s3.equals(s4));	// true
        System.out.println(s3 == s4);		// true

        System.out.println("-------------");

        String s5 = s1 + s2;
        System.out.println(s4.equals(s5));	// true
        System.out.println(s4 == s5);		// false

        System.out.println("-------------");

        String s6 = (s1 + s2).intern();
        System.out.println(s4.equals(s6));	// true
        System.out.println(s4 == s6);		// true
    }
}

注意事项:

使用 + 拼接多个字符串常量,拼接的结果仍旧是字符串常量

如果结果字符串常量在常量池中不存在,则Java会将其放入到字符串常量池中

//final修饰的也是常量
public static void main(String[] args) {
    String str = "ab";

    String s1 = "a";
    // String msg = new String("a"+"b");
    String msg = s1 + "b";
    System.out.println(msg == str);     //false

    //如果final修饰的变量参与运算,等同于字面值常量
    final String s2 = "a";
    // String msg2 = "a" + "b";
    String msg2 = s2 + "b";

    System.out.println(msg2 == str);    //true
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值