目录
2. String s = new String("xyz");创建了几个String Object?
3. String a="abc" String b="a"+"bc" 问a==b?
12. StringBuilder和StringBuffer的线程安全问题
13. 简单说说 Comparable 和 Comparator 的区别和场景?
14. Comparable 接口和 Comparator 接口实现比较
1. 以下两种方式创建的String对象有什么不同?
String str = new String("test");
String str = "test";
new String("test")
创建新的对象,即使内容相同也会占用新的内存空间。String str = "test";
更高效,适合常用字符串的初始化操作,因为会复用字符串池中的对象。
2. String s = new String("xyz");创建了几个String Object?
String s = new String("xyz");
实际上创建了 两个 String
对象。
解释
- 字符串字面量
"xyz"
:- 首先,编译器会在字符串池中查找是否已经存在
"xyz"
。 - 如果字符串池中没有
"xyz"
,则会将"xyz"
放入池中。 - 如果已经存在
"xyz"
,则直接使用池中的对象,而不创建新的对象。
- 首先,编译器会在字符串池中查找是否已经存在
new String("xyz")
创建的新对象:new String("xyz")
强制在堆内存中创建一个新的String
对象,无论字符串池中是否已有"xyz"
。- 因此,这个新的对象和池中的对象是不同的,且它不会与字符串池中的
"xyz"
共享。
3. String a="abc" String b="a"+"bc" 问a==b?
结果是为 true。由于编译时的常量优化,"a" + "bc"
直接在编译期被计算为 "abc"
,所以 a
和 b
都指向同一个字符串池中的对象。
4. String 中 “+” 怎样实现?
变量 + 常量 、变量+变量:创建一个StringBuilder的实例,通过append()添加字符串,最后调用toString()返回一个字符串。(toString()内部new 一个String的实例)
5. Java中String是不是final的?
String
类被声明为 final
,主要是为了保持它的不可变性、安全性和性能的优化。这种设计在 Java 中广泛使用,使得 String
可以在字符串池中复用,减少内存消耗并提升程序性能。
6. String为啥不可变,在内存中的具体形态?
String
的不可变性主要由final
修饰的字符数组char[]
和字符串池的设计来保证。- 不可变的
String
对象使得字符串池的复用、哈希缓存和线程安全成为可能,从而优化了 Java 程序的性能和内存效率。
7. String 可以在 switch中使用吗?
在 switch
中使用 String
是安全且便捷的,对于匹配一组已知字符串非常有用。需要注意避免使用 null
值来确保代码安全。
8. String中有哪些方法?列举几个
1. 长度和字符获取
int length()
:返回字符串的长度。char charAt(int index)
:返回指定索引处的字符。
2. 查找和比较
boolean equals(Object obj)
:比较两个字符串的内容是否相同。boolean equalsIgnoreCase(String anotherString)
:忽略大小写地比较两个字符串是否相同。int compareTo(String anotherString)
:按字典顺序比较两个字符串。int compareToIgnoreCase(String str)
:忽略大小写按字典顺序比较两个字符串。boolean contains(CharSequence sequence)
:判断字符串是否包含指定的字符序列。boolean startsWith(String prefix)
:判断字符串是否以指定前缀开始。boolean endsWith(String suffix)
:判断字符串是否以指定后缀结束。int indexOf(String str)
:返回指定子字符串第一次出现的索引。int lastIndexOf(String str)
:返回指定子字符串最后一次出现的索引。
3. 字符串提取
String substring(int beginIndex)
:返回从指定位置开始的子字符串。String substring(int beginIndex, int endIndex)
:返回指定范围内的子字符串。
4. 字符串修改
String toLowerCase()
:将字符串转换为小写。String toUpperCase()
:将字符串转换为大写。String trim()
:去除字符串首尾的空白字符。String replace(char oldChar, char newChar)
:替换字符串中所有指定的字符。String replaceAll(String regex, String replacement)
:使用正则表达式替换所有匹配的子字符串。String replaceFirst(String regex, String replacement)
:使用正则表达式替换第一个匹配的子字符串。
5. 分割和连接
String[] split(String regex)
:根据指定的正则表达式将字符串分割为数组。String join(CharSequence delimiter, CharSequence... elements)
:将多个字符序列连接为一个字符串,并在每个元素之间插入分隔符。
6. 字符串内容检查
boolean isEmpty()
:判断字符串是否为空(长度为 0)。boolean isBlank()
:判断字符串是否为空或只包含空白字符(Java 11 新增)。
7. 转换与格式化
String valueOf(Object obj)
:将对象转换为字符串。String format(String format, Object... args)
:格式化字符串。
9. subString()到底做了什么?
String str = "hello";
String subStr = str.subString(1,3); //底层是new的方式返回一个subStr,实体内容是"el"
10. Java中操作字符串有哪些类?他们之间有什么区别。
> String:不可变的字符序列;底层使用char[] (jdk8及之前),底层使用byte[] (jdk9及之后)
> StringBuffer:可变的字符序列;JDK1.0声明,线程安全的,效率低;底层使用char[] (jdk8及之前),底层使用byte[] (jdk9及之后)
> StringBuilder:可变的字符序列;JDK5.0声明,线程不安全的,效率高;底层使用char[] (jdk8及之前),底层使用byte[] (jdk9及之后)
11. String的线程安全问题
在 Java 中,String
是线程安全的,这是因为 String
是不可变的(immutable)。
虽然 String
是线程安全的,但使用 String
进行频繁的拼接操作时仍然会带来性能问题,因为每次拼接都会创建新的 String
对象,占用额外内存。因此,在多线程环境下处理大量字符串拼接时,推荐使用 StringBuilder
或 StringBuffer
:
StringBuilder
:适合在单线程中进行字符串拼接,性能较高。StringBuffer
:是线程安全的,可用于多线程场景,因为它的主要方法都被synchronized
关键字修饰。
12. StringBuilder和StringBuffer的线程安全问题
StringBuilder
是非线程安全的,但性能高,适合单线程使用。StringBuffer
是线程安全的,适合多线程环境中对字符串进行并发操作。
13. 简单说说 Comparable 和 Comparator 的区别和场景?
- 单一排序标准:用
Comparable
,类实现自然排序。 - 多种排序标准:用
Comparator
,根据需求定义多个比较器。
14. Comparable 接口和 Comparator 接口实现比较
1. Comparable 接口的实现
- 自带排序:
Comparable
接口为类提供一种默认的“自然排序”方式。 - 单一排序标准:只能定义一种排序规则,类本身负责实现。
实现方式
- 实现
Comparable
接口的类必须重写compareTo
方法。 compareTo(T o)
方法返回一个整数值:负值
:当前对象小于比较对象。0
:两个对象相等。正值
:当前对象大于比较对象。
2. Comparator 接口的实现
- 自定义排序:
Comparator
接口用于提供类的多种排序方式。 - 多种排序标准:可以实现多个
Comparator
,并根据不同需求定义不同的排序规则。
实现方式
Comparator
是一个独立的类(或匿名类),并不需要修改被排序的类。- 需重写
compare(T o1, T o2)
方法来指定排序逻辑:负值
:o1
小于o2
。0
:o1
等于o2
。正值
:o1
大于o2
。