4

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

 3 years ago
source link: https://blog.csdn.net/wj1314250/article/details/116807402
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

面试字节我被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对象

<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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK