JVM-02:字符串常量池

本文详细解析了Java中字符串常量池的工作原理,包括字符串的创建方式、常量池的作用以及不同情况下的对象比较。重点讲解了final关键字和new操作符对字符串对象的影响,并通过实例展示了8种基本类型包装类的常量池应用。
摘要由CSDN通过智能技术生成
String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";//常量池中的对象
String str4 = str1 + str2; //在堆上创建的新的对象
String str5 = "string";//常量池中的对象
System.out.println(str3 == str4);//false
System.out.println(str3 == str5);//true
System.out.println(str4 == str5);//false

对于编译期可以确定值的字符串,也就是常量字符串 ,jvm 会将其存入字符串常量池。

字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建。

String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
System.out.println(aa==bb);// true

JDK1.7 之前运行时常量池逻辑包含字符串常量池存放在方法区。JDK1.7 的时候,字符串常量池被从方法区拿到了堆中。

对象引用和“+”的字符串拼接方式,实际上是通过 StringBuilder 调用 append() 方法实现的,拼接完成之后调用 toString() 得到一个 String 对象 。 

String str4 = new StringBuilder().append(str1).append(str2).toString();

不过,字符串使用 final 关键字声明之后,可以让编译器当做常量来处理。

final String str1 = "str";
final String str2 = "ing";
// 下面两个表达式其实是等价的
String c = "str" + "ing";// 常量池中的对象
String d = str1 + str2; // 常量池中的对象
System.out.println(c == d);// true

只要使用 new 的方式创建对象,便需要创建新的对象 。

使用 new 的方式创建对象的方式如下,可以简单概括为 3 步:

  1. 在堆中创建一个字符串对象
  2. 检查字符串常量池中是否有和 new 的字符串值相等的字符串常量
  3. 如果没有的话需要在字符串常量池中也创建一个值相等的字符串常量,如果有的话,就直接返回堆中的字符串实例对象地址。

因此,str2 和 str3 都是在堆中新创建的对象。

4.2 String s1 = new String("abc");这句话创建了几个字符串对象?

会创建 1 或 2 个字符串:

  • 如果字符串常量池中已存在字符串常量“abc”,则只会在堆空间创建一个字符串常量“abc”。
  • 如果字符串常量池中没有字符串常量“abc”,那么它将首先在字符串常量池中创建,然后在堆空间中创建,因此将创建总共 2 个字符串对象.

4.3 8 种基本类型的包装类和常量池

Java 基本类型的包装类的大部分都实现了常量池技术。

Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True Or False

Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);

Integer i1=40 这一行代码会发生装箱,也就是说这行代码等价于 Integer i1=Integer.valueOf(40) 。因此,i1 直接使用的是常量池中的对象。而Integer i2 = new Integer(40) 会直接创建新的对象。

因此,答案是 false 。你答对了吗?

记住:所有整型包装类对象之间值的比较,全部使用 equals 方法比较

 

Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);

System.out.println(i1 == i2);// true
System.out.println(i1 == i2 + i3);//true
System.out.println(i1 == i4);// false
System.out.println(i4 == i5);// false
System.out.println(i4 == i5 + i6);// true
System.out.println(40 == i5 + i6);// true

 关于i4 == i5 + i6;

左边对象 == 对象 + 对象

但是 i5 + i6在运算的时候会自动拆箱;所以就变为了数值 40 + 数值 0;结果为数值40;

左边对象 == 数值40;对象和数值不能直接比较,所以需要对左边的对象i4进行自动拆箱;

左边对象i4拆箱为数值40;最终结果为:40 == 40;返回true;

关于 i1 == 14;左边对象;右边对象,两边都是对象可以直接进行比较;因为用==比较的时候比较的是地址值;所以返回false;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小馨java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值