1、String 的基本特性

1.1、String 概述

  1、String:字符串,使用一对 “” 引起来表示

1 String s1 = "mogublog" ;               // 字面量的定义方式
2 String s2 =  new String("moxi");     // new 对象的方式

  2、String声明为final的,不可被继承

  3、String实现了Serializable接口:表示字符串是支持序列化的。实现了Comparable接口:表示String可以比较大小

  4、string在jdk8及以前内部定义了final char[] value用于存储字符串数据。JDK9时改为byte[]

  为什么 JDK9 改变了 String 的结构

  官方文档:http://openjdk.java.net/jeps/254

  为什么改为 byte[] 存储?

  1. String类的当前实现将字符存储在char数组中,每个字符使用两个字节(16位)。

  2. 从许多不同的应用程序收集的数据表明,字符串是堆使用的主要组成部分,而且大多数字符串对象只包含拉丁字符。这些字符只需要一个字节的存储空间,因此这些字符串对象的内部char数组中有一半的空间将不会使用。

  3. 之前 String 类使用 UTF-16 的 char[] 数组存储,现在改为 byte[] 数组 外加一个编码标志位存储,该编码标志将指定 String 类中 byte[] 数组的编码方式

  4. 结论:String再也不用char[] 来存储了,改成了byte [] 加上编码标记,节约了一些空间

  5. 同时基于String的数据结构,例如StringBuffer和StringBuilder也同样做了修改

1 // 之前
2 private final char value[];
3 // 之后
4 private final byte[] value

1.2、String 的基本特征

  String:代表不可变的字符序列。简称:不可变性。

  1. 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。

  2. 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。

  3. 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。

  通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。

   1)当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值  

  • 代码
     1 @Test
     2 public void test1() {
     3     String s1 = "abc";//字面量定义的方式,"abc"存储在字符串常量池中
     4     String s2 = "abc";
     5     s1 = "hello";
     6 
     7     System.out.println(s1 == s2);//判断地址:false
     8 
     9     System.out.println(s1);//hello
    10     System.out.println(s2);//abc
    11 }
  • 字节码指令

    • 取字符串 “abc” 时,使用的是同一个符号引用:#2

    • 取字符串 “hello” 时,使用的是另一个符号引用:#3

      0 ldc #2 <abc>
       2 astore_1
       3 ldc #2 <abc>
       5 astore_2
       6 ldc #3 <hello>
       8 astore_1
       9 getstatic #4 <java/lang/System.out>
      12 aload_1
      13 aload_2
      14 if_acmpne 21 (+7)
      17 iconst_1
      18 goto 22 (+4)
      21 iconst_0
      22 invokevirtual #5 <java/io/PrintStream.println>
      25 getstatic #4 <java/lang/System.out>
      28 aload_1
      29 invokevirtual #6 <java/io/PrintStream.println>
      32 getstatic #4 <java/lang/System.out>
      35 aload_2
      36 invokevirtual #6 <java/io/PrintStream.println>
      39 return

  2)当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值

  • 代码
    1 @Test
    2 public void test2() {
    3     String s1 = "abc";
    4     String s2 = "abc";
    5     s2 += "def";
    6     System.out.println(s2);//abcdef
    7     System.out.println(s1);//abc
    8 }
  • 字节码指令:拼接操作通过 StringBuilder 的 append() 方法完成
     0 ldc #2 <abc>
     2 astore_1
     3 ldc #2 <abc>
     5 astore_2
     6 new #7 <java/lang/StringBuilder>
     9 dup
    10 invokespecial #8 <java/lang/StringBuilder.<init>>
    13 aload_2
    14 invokevirtual #9 <java/lang/StringBuilder.append>
    17 ldc #10 <def>
    19 invokevirtual #9 <java/lang/StringBuilder.append>
    22 invokevirtual #11 <java/lang/StringBuilder.toString>
    25 astore_2
    26 getstatic #4 <java/lang/System.out>
    29 aload_2
    30 invokevirtual #6 <java/io/PrintStream.println>
    33 getstatic #4 <java/lang/System.out>
    36 aload_1
    37 invokevirtual #6 <java/io/PrintStream.println>
    40 return 

  3)当调用string的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值

  • 代码
    1 @Test
    2 public void test3() {
    3     String s1 = "abc";
    4     String s2 = s1.replace('a', 'm');
    5     System.out.println(s1);//abc
    6     System.out.println(s2);//mbc
    7 }
  • 来看看 replace() 方法的源码,new String(buf, true); 后,返回新的 String 对象

     1 public String replace(char oldChar, char newChar) {
     2     if (oldChar != newChar) {
     3         int len = value.length;
     4         int i = -1;
     5         char[] val = value; /* avoid getfield opcode */
     6 
     7         while (++i < len) {
     8             if (val[i] == oldChar) {
     9                 break;
    10             }
    11         }
    12         if (i < len) {
    13             char buf[] = new char[len];
    14             for (int j = 0; j < i; j++) {
    15                 buf[j] = val[j];
    16             }
    17             while (i < len) {
    18                 char c = val[i];
    19                 buf[i] = (c == oldChar) ? newChar : c;
    20                 i++;
    21             }
    22             return new String(buf, true);
    23         }
    24     }
    25     return this;
    26 }
    View Code

相关文章:

  • 2021-06-20
  • 2021-06-29
  • 2021-11-25
  • 2022-12-23
  • 2022-12-23
  • 2022-01-03
  • 2021-10-05
  • 2021-09-01
猜你喜欢
  • 2022-12-23
  • 2021-06-29
  • 2021-10-16
  • 2022-12-23
  • 2021-12-06
  • 2022-12-23
相关资源
相似解决方案