面试字节我被String类的问题给问死了!

Java架构没有996
• 阅读 1713

面试字节我被String类的问题给问死了! "+" 是怎么连接字符串的?(JDK1.7及以上) 总结:

使用 "+" 连接字符串时,实际上是使用临时创建的StringBuilder对象来辅助完成的。 对于编译时常量,在编译后直接计算出字符串的值,而不会在运行时创建临时的StringBuilder对象来完成字符串连接。 在循环中对String对象进行连接,应该直接使用StringBuilder代替 "+",这样可以提高性能。 注意: 当使用运算符 "+" 连接字符串时,如果两个操作数都是编译时常量,则在编译时期就会计算该字符串的值,而不会在运行时创建StringBuilder对象。


final String s = "abc";
String x = "abc" + "def"; // 两个操作数都是常量,运行时不会创建StringBuilder对象
String y = s + "def"; // s和"def"都是编译时常量,不会创建StringBuilder对象,实际上x和y指向同一个对象,即"abcdef"
String z = y + "abc"; // y是变量,则在运行时会创建StringBuilder对象

面试字节我被String类的问题给问死了!

不可修改的String对象

<1> 问:String对象一经创建,不能修改,为什么?

因为String类是final类型的,无法继承该类。

其所有的成员变量都是private的,并且没有提供修改私有成员变量的公有(public)方法 对String对象的操作都没有修改当前对象,而是新创建一个对象

<2> 问:把String对象设计成不可修改有什么好处吗?

最大好处就是可以实现资源共享,多线程操作时,具有线程安全性。

总结三点:

  • String类是final类型的,其对象一旦创建,不可修改。
  • String类那些看似修改字符序列的方法实际上都是返回新创建的String对象,而不是修改自身对象。
  • String对象不可改变,因此具有线程安全性,可自由实现共享。

String类的内部实现 在String类内部,使用一个字符数组char[]来维护字符序列。

private final char value[];

问:String的最大长度是多少?

String的最大长度也就是字符数组char[]的最大长度,理论上为int类型的最大值,即2147483647,实际上,一般可获取的最大值小于理论最大值。

申请一个int最大值长度字符数组:

char c = new char[Integer.MAX_VALUE]; // 报错

报错:一个char类型占用2字节,Integer.MAX_VALUE个char类型接近于4GB大小,申请这么大一块连续内存空间,导致内存溢出。 //加入Java开发交流君样:756584822一起吹水聊天

分析:Java中的对象是分配在堆上的,默认的堆空间的最大值是256MB,在理想的情况下,只要我们将最大Java堆设置的足够大,就可以申请到最大的字符长度,即Integer.MAX_VALUE。

java -Xmx1G com.fan.fragmentlearning.str.StringDemoMain -- 设置Main方法最大Java堆

String常量池

<1> 什么是String常量池?

String常量池是String类内部私有的,能够自动将String字面常量加入其中。 起初,常量池是空的,当程序中出现String字面常量时,会在常量池中搜索是否存在该String对象,即使用String类的equals方法来判断,如果不存在,就将这个字面常量加入常量池中,并返回该对象;否则直接返回常量池中的对象。

<2> String字面常量和String常量表达式都会加入常量池中。

<3> 满足什么条件才算是String常量表达式呢?

即就是在编译的时候就可以确定其值的String类型表达式。编译器的原则是:能在编译期间计算的,就不会留到运行时再去计算。

第一种: 表达式全部由String字面常量拼接

String s = "a" + "b" + "c";

第二种: 表达式由String字面常量,基本类型字面常量,final修饰的String引用,final修饰的基本数据类型任意组合组成。

String s = "a" + 5; // String常量表达式

final String str = "a";
String s = "bc" + str; // String常量表达式

final int num = 5;
String s = "a" + num; // String常量表达式

String s = str + num; // String常量表达式

<4> intern方法 - 拘留字符串

如果需要将某个String对象加入常量池中,就可以调用intern方法来完成,这个操作也称作拘留字符串。 系统自动将String字面常量与String常量表达式的字符串值加入常量池中,也是通过调用intern方法来实现的。

要点总结:

String类维护一块特殊的区域,称为常量池。因为String对象是不可改变的,因此没有必要创建两个相同的String对象。只需将String对象加入常量池,在需要的时候取出,这样即可实现String对象的共享。 在程序中出现String编译时常量(String字面常量与String常量表达式),会自动调用intern方法,如果常量池中含有相等的String对象(使用String类的equals方法来判断),则直接返回常量池中的对象;否则将对象加入常量池中并返回该对象。 对于运行时创建的String对象(非String编译时常量),会分配到堆中,系统不会自动调用intern方法拘留该对象,不过我们依然可以自行调用该对象的intern方法对该对象进行拘留。

最新2020整理收集的一些高频面试题(都整理成文档),有很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,也有详细的学习规划图,面试题整理等,需要获取这些内容的朋友请加Q君样:756584822

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
java中stringBuilder的用法
String对象是不可改变的。每次使用System.String类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新的String对象相关的系统开销可能会非常昂贵。如果要修改字符串而不创建新的对象,则可以使用System.Text.StringBuilder类。例如,当在一个循
Wesley13 Wesley13
3年前
String、StringBuffer、StringBuilder的区别
String字符串常量StringBuffer字符串变量(线程安全)StringBuilder字符串变量(非线程安全) 简要的说,String类型和StringBuffer类型的主要性能区别其实在于String是不可变的对象,因此在每次对String类型进行改变的时候其实都等同于生成了一个新的String
Easter79 Easter79
3年前
String ,StringBuffer ,StringBuilder 三者的理解
1.String,StringBuffer,StringBuilder三者执行效率的问题StringBuilderStringBufferStringString是字符常量,是不可变的.如果拿String来操作字符串,一旦操作的字符串的值改变了,就会在内存中创建多一个空间来保存新的字符串,这样的话String的效率就比较低下了.
Stella981 Stella981
3年前
BATJ的常见java面试题
JAVA基础1.JAVA中的几种基本数据类型是什么,各自占用多少字节。2.String类能被继承吗,为什么。不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。3.String,Stringbuffer,StringBuilder的区别。String字符串常量StringBuffer
Wesley13 Wesley13
3年前
unity将 -u4E00 这种 编码 转汉字 方法
 unity中直接使用 JsonMapper.ToJson(对象),取到的字符串,里面汉字可能是\\u4E00类似这种其实也不用转,服务器会通过类似fastjson发序列化的方式,将json转对象,获取对象的值就是中文但是有时服务器要求将传参中字符串中类似\\u4E00这种转汉字,就需要下面 publ