拿下java字符串,面试不再露出马脚

字符串变量

定义一个字符串变量并初始化非常简单

String s = "hello world";

这种方式称为 字符串字面量(String Literal) 创建。

但是要 new 一个String出来就没有这么简单
在这里插入图片描述
可以看到有很多重载方法,这里介绍几个最经使用的

String s1 = new String();
String s2 = new String("hello world"); // hello world

byte[] bytes = {104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100};
String s3 = new String(bytes); // hello world

在jdk提供的类中,很多字符操作的底层都是通过字节数组来实现的,本质上这些数字对应这ASCII码表的字符。

温馨提示:当你你要的字符需要转义时,你可以直接通过字节数组构造。byte是一个字节,存储数的范围是-128~127。

s2保存的是什么?
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/648e0000262e47128679ac70cebc2fe2.png
这是创建s2的内存简单示意图,s2实际上是保存对象的引用,也就是在堆区的地址。在调用toString方法的时候底层经过了处理,返回的不是地址。

字符串内存

在此之前我们来了解一下字符串常量池(String Table),我们知道String类是字符不可变的,当改变字符其实就是创建了新的String对象。常量池的存在就是为了提高字符串的利用效率。

本篇文章并不详细探讨String Table的实现,事实上String Table在jdk1.8不是由java实现的

什么时候会把字符串对象放入常量池?
可以通过一道简单的面试题来揭露一角

题目:String a = new String("1")创建了多少个对象

答:创建了一个或两个对象,运行这个语句首先会在堆中创建新的字符串对象;另外,如果该字符串对象的值在常量池中不存在的话,还会在常量池中创建一个新的字符串对象(已有则不用创建)。

我们来看一下最简单的例子

String s = new String("123");
String s1 = "123";
String s2 = "123";
System.out.println(s1 == s); // true
System.out.println(s1 == s2); // false
  1. 在堆区创建新的字符串对象,同时常量池为空,创建新的字符串对象
  2. 通过字符串字面量方式创建,先在常量池寻找是否存在值相等的对象,有则返回地址
  3. s2同理,保存的是常量池值相等对象的地址

内存示意图:
在这里插入图片描述

当我们需要判断字符串内容是否相等请使用equalequalsIgnoreCase

字符串的拼接底层原理

  1. 字符串字面量相拼接
String s = "abc123";
String s1 = "abc" + "123";
System.out.println(s == s1); // true

为什么是true,不妨打开编译后的class文件
在这里插入图片描述
可以看到class文件直接就是“abc123”,因为jvm对其进行了优化,s和是拿到的都是常量池的“abc123”,所以相等

  1. 变量参与拼接
String s1 = "abc";
String s2 = "123";
String s3 = s1 + "123";
String s4 = s1 + s2;

通过javap -c命令反编译来查看
在这里插入图片描述
可以看到只要有变量参与,都使用了makeConcatWithConstants来进行优化。

在jdk8之前是使用StringBuilder(或StringBuffer)来做的,开销比较大,感兴趣的可以去看看。

回到makeConcatWithConstants,我们来大致了解一下它的工作流程。首先Ctrl + N找到这个方法,在java.lang.invoke包下
在这里插入图片描述

  • lookup:MethodHandles.Lookup 对象,用于在运行时查找和操作方法。
  • name:字符串,可能是方法的名称。
  • concatType:MethodType,表示拼接操作的方法类型。
  • recipe:字符串,可能是用于指定拼接规则或配方的参数。
  • constants:对象数组,可能包含用于拼接的常量。

本质上会创建一个数组进行字符串拼接

如果大家感兴趣我就再扒一扒makeConcatWithConstants的原理~

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值