ToB企服应用市场:ToB评测及商务社交产业平台

标题: Java中的这些String特性可能需要了解下 [打印本页]

作者: 商道如狼道    时间: 2024-5-20 11:12
标题: Java中的这些String特性可能需要了解下
先总结下,String类具有以下特性:
下文将详细阐明这些特性。
本文基于JDK17阐明。
不可变性(Immutable)

String的不可变性指的是一旦创建了String对象,它的值就不能被修改。
这意味着在任何对String对象进行操纵时,都会返回一个新的String对象,而原始对象的值保持稳定。
这种特性有助于保护数据的同等性,并且在多线程环境下也更加安全。
下面是一个示例来阐明String的不可变性:
  1. public class ImmutableStringExample {
  2.     public static void main(String[] args) {
  3.         String original = "Hello";
  4.         String modified = original.concat(", World!");
  5.         
  6.         System.out.println("Original string: " + original);
  7.         System.out.println("Modified string: " + modified);
  8.     }
  9. }
复制代码
输出结果为:
  1. Original string: Hello
  2. Modified string: Hello, World!
复制代码
在这个例子中,虽然使用了 concat 方法对原始字符串进行了修改,但是原始字符串 original 的值并没有改变。相反,concat 方法返回了一个新的字符串对象,此中包含了修改后的值。
此中concat函数的主要代码如下:
  1. @ForceInline
  2. static String simpleConcat(Object first, Object second) {
  3.     String s1 = stringOf(first);
  4.     String s2 = stringOf(second);
  5.     if (s1.isEmpty()) {
  6.         // 直接返回s2参数
  7.         return new String(s2);
  8.     }
  9.     if (s2.isEmpty()) {
  10.         // 直接返回s1参数
  11.         return new String(s1);
  12.     }
  13.     // start "mixing" in length and coder or arguments, order is not
  14.     // important
  15.     long indexCoder = mix(initialCoder(), s1);
  16.     indexCoder = mix(indexCoder, s2);
  17.     byte[] buf = newArray(indexCoder);
  18.     // prepend each argument in reverse order, since we prepending
  19.     // from the end of the byte array
  20.     indexCoder = prepend(indexCoder, buf, s2);
  21.     indexCoder = prepend(indexCoder, buf, s1);
  22.     // 返回新建的String对象
  23.     return newString(buf, indexCoder);
  24. }
复制代码
String的不可变性对于计划具有很多长处。
String的不可变性使得它在Java中成为一种简单、安全且高效的数据结构。
不可变性怎么保证的

String 的不可变性是通过类的计划、内部实现和方法计划来保证的,这种不可变性使得 String 对象在多线程环境下更加安全,并且可以被方便地共享和重用。
String 的不可变性是通过以下几种方式来保证的:
如下是String对象的部分源码,可以看到value和对象都被final修饰。
  1. public final class String
  2.     implements java.io.Serializable, Comparable<String>, CharSequence,
  3.                Constable, ConstantDesc {
  4.     @Stable
  5.     private final byte[] value;
  6.     // ...
  7. }
复制代码
值通报

在Java中,String对象的通报是通过值通报(pass by value)进行的。
这意味着在将String对象通报给方法或赋值给另一个变量时,通报的是对象的副本而不是对象本身。
当你将一个String对象通报给方法时,实际上通报的是对象的引用的副本,而不是对象本身。这意味着方法内部的操纵不会影响原始的String对象,由于它们操纵的是副本。
下面是一个示例来阐明String的值通报:
  1. public class StringValuePassingExample {
  2.     public static void main(String[] args) {
  3.         String original = "Hello";
  4.         modifyString(original);
  5.         System.out.println("Original string after method call: " + original);
  6.     }
  7.     public static void modifyString(String str) {
  8.         str = str + ", World!";
  9.         System.out.println("Modified string inside method: " + str);
  10.     }
  11. }
复制代码
输出结果为:
  1. Modified string inside method: Hello, World!
  2. Original string after method call: Hello
复制代码
在这个例子中,虽然在 modifyString 方法内部对 str 进行了修改,但原始的 original 字符串并没有受到影响。这是由于在方法调用时,通报的是 original 字符串的副本,而不是原始对象本身。
因此,在方法内部对 str 的任何修改都不会影响原始的 original 字符串。
字符串存储在StringTable

StringTable是一种特殊的内存区域,用于存储字符串常量。
当创建字符串时,如果该字符串已经存在于StringTable中,则直接返回对该字符串的引用,而不会创建新的字符串对象;如果该字符串不在StringTable中,则会创建一个新的字符串对象,并将其添加到StringTable中。
如果字符串是动态创建的,好比通过new、concat、substring、toUpperCase动态创建的会放到堆内存中。
StringTable、字符串、堆的表示图如下所示:

StringTable的计划有几个主要缘故原由:
字符串比拼
  1. import java.util.HashMap;
  2. public class StringTableDemo {
  3.     public static void main(String[] args) {
  4.         String str1 = "abc";
  5.         String str2 = new String("abc");
  6.         System.out.println(str1 == str2);//false
  7.         String str3 = new String("abc");
  8.         System.out.println(str3 == str2);//false
  9.         String str4 = "a" + "b";
  10.         System.out.println(str4 == "ab");//true
  11.         String s1 = "a";
  12.         String s2 = "b";
  13.         String str6 = s1 + s2;
  14.         System.out.println(str6 == "ab");//false
  15.         String str7 = "abc".substring(0, 2);
  16.         System.out.println(str7 == "ab");//false
  17.         String str8 = "abc".toUpperCase();
  18.         System.out.println(str8 == "ABC");//false
  19.         String s5 = "a";
  20.         String s6 = "abc";
  21.         String s7 = s5 + "bc";
  22.         System.out.println(s6 == s7.intern());//true
  23.     }
  24. }
复制代码
通过以上的例子可以总结出以下规律:
关于作者

来自全栈程序员nine的探索与实践,连续迭代中。
欢迎关注和点赞~

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4