spring - string
spring - string
1.string
在 Java 8 及之前的版本中,字符串由不可变的 Unicode 字符数组组成。然而,大多数字符只需要 8 位(1 个字节)来表示它们,而不是 16 位(字符大小)。
为了改善内存消耗和性能,Java 9 引入了紧凑字符串。这意味着如果字符串仅包含 1 字节字符,它将使用Latin-1编码表示。如果字符串至少包含 1 个多字节字符,则使用 UTF-16 编码将其表示为每个字符 2 个字节。
在 C 和 C++ 中,String也是一个字符数组,但在 Java 中,它是一个具有自己的 API 的单独对象。
2.字符串不可变有什么好处
根据James Gosling 的采访,字符串是不可变的,以提高性能和安全性。
实际上,我们看到了使用不可变字符串的几个好处:
2.1仅当字符串一旦创建就永远不会更改时,字符串池才是可能的,因为它们应该被重用
2.2该代码可以安全地将字符串传递给另一个方法,因为知道该方法无法更改它
2.3不可变地自动使此类成为线程安全的
2.4由于该类是线程安全的,因此 不需要同步公共数据,从而提高了性能
2.5由于保证它们不会改变,因此可以轻松缓存它们的哈希码
3.字符串如何存储在内存中
根据 JVM 规范,字符串文字存储在 运行时常量池中,该常量池是从 JVM 的方法区分配的。
尽管方法区在逻辑上是堆内存的一部分,但规范并未规定位置、内存大小或垃圾收集策略。它可以是特定于实现的。
类或接口的运行时常量池是在 JVM 创建类或接口时构造的。
4.什么是字符串常量池
字符串池,也称为 字符串常量池或 字符串实习池,是 JVM 存储String实例的特殊内存区域。
它通过减少分配字符串的频率和数量来优化应用程序性能:
JVM在池中仅存储特定字符串的一份副本
当创建一个新的String时,JVM 在池中搜索具有相同值的String
如果找到,JVM 将返回对该字符串的引用,而不分配任何额外的内存
如果没有找到,那么 JVM 将其添加到池中(实习它)并返回其引用
5.字符串是线程安全的吗
字符串确实是完全线程安全的,因为它们是不可变的。任何不可变的类都会自动符合线程安全性,因为它的不可变性保证了其实例不会在多个线程中更改。
例如,如果线程更改字符串的值,则会创建一个新 字符串 ,而不是修改现有字符串。
6.我们如何在 Java 中比较两个字符串?str1 == str2和str1.equals(str2)之间有什么区别?
运算符 ( str1 == str2 ) 检查引用相等性
方法 ( str1.equals(str2) ) 检查词法相等
7. 什么是 Stringjoiner
StringJoiner 是 Java 8 中引入的一个类,用于将单独的字符串连接成一个,例如获取颜色列表并将它们作为逗号分隔的字符串返回。我们可以提供分隔符以及前缀和后缀:
StringJoiner joiner = new StringJoiner(",", "[", "]");
joiner.add("Red")
.add("Green")
.add("Blue");
assertEquals("[Red,Green,Blue]", joiner.toString());
8.String、Stringbuffer 和 Stringbuilder 之间的区别?
字符串是不可变的。这意味着如果我们尝试更改或改变它的值,那么 Java 会创建一个绝对新的String。
例如,如果我们在创建字符串str1 后添加它:
String str1 = "abc";
str1 = str1 + "def";
然后 JVM 不会修改str1,而是创建一个全新的String。
然而,对于大多数简单的情况,编译器内部使用StringBuilder并优化上述代码。
但是,对于更复杂的代码(例如循环),它将创建一个全新的String,从而降低性能。这就是StringBuilder和StringBuffer有用的地方。
Java 中的StringBuilder和StringBuffer都创建保存可变字符序列的对象。StringBuffer 是同步的,因此是线程安全的,而StringBuilder不是。
由于StringBuffer 中的额外同步 通常是不必要的,因此我们通常可以通过选择 StringBuilder 来提高性能 。
9.String 的 intern() 方法有什么作用?
intern()方法 在堆中 创建String对象 的精确副本 ,并将其存储在JVM 维护的String 常量池中。
Java 会自动驻留所有使用字符串文字创建的字符串,但如果我们使用 new 运算符创建 String ,例如String str = new String(“abc”),那么 Java 会将其添加到堆中,就像任何其他对象一样。
我们可以调用 intern()方法来告诉 JVM 将其添加到字符串池(如果字符串池中尚不存在),并返回该 interned 字符串的引用:
String s1 = "Baeldung";
String s2 = new String("Baeldung");
String s3 = new String("Baeldung").intern();
assertThat(s1 == s2).isFalse();
assertThat(s1 == s3).isTrue();
10.常见方法
char[] hello = "hello".toCharArray();
assertArrayEquals(new String[] { 'h', 'e', 'l', 'l', 'o' }, hello);
byte[] byteArray2 = "efgh".getBytes(StandardCharsets.US_ASCII);
byte[] byteArray3 = "ijkl".getBytes("UTF-8");
long count = "hello".chars().filter(ch -> (char)ch == 'l').count();
assertEquals(2, count);
String reversed = new StringBuilder("baeldung").reverse().toString();
assertEquals("gnudleab", reversed);