String概述


String的基本特性

  • String是字符串,使用一對引號("")包裝。

  • String聲明是final的,不可被繼承。

  • String實現了Serializable接口,表示字符串是支持序列化的;實現了Comparable接口,表示String可以比較大小。

  • String在jdk8及以前內部定義了final char[] value用於存儲字符數據,jdk9時改為byte[]

  • String是不可變的字符序列。簡稱:不可變性。

    • 當對字符串重新賦值時,需要重寫指定內存區域賦值,不能使用原有的value進行賦值。

      /**
       * 第一次執行, 注釋掉s1 = "hello";
       */
      @Test
      public void test1() {
          String s1 = "abc";
          String s2 = "abc";
          s1 = "hello";
      
          System.out.println(s1 == s2); // 1st. true        2nd. false
          System.out.println(s1);       // 1st. abc         2nd. abc
          System.out.println(s2);       // 1st. abc         2nd. hello
      }
      
    • 當對現有的字符串進行連續操作時,也需要重新指定內存區域賦值,不能使用原有的value進行賦值。

      @Test
      public void test2() {
          String s1 = "abc";
          String s2 = "abc";
          s2 += "def";
          System.out.println(s1); // abc
          System.out.println(s2); // abcdef
      }
      
    • 當調用String的replace()方法修改指定字符或字符串時,也需要重新指定內存區域賦值,不能使用原有的value進行賦值。

      @Test
      public void test3() {
          String s1 = "abc";
          String s2 = s1.replace('a', 'z');
          System.out.println(s1); // abc
          System.out.println(s2); // zbc
      }
      
package com.chinda.java.base;

/**
 * @author Wang Chinda
 * @date 2020/5/29
 * @see
 * @since 1.0
 */
public class StringExer {

    String str = new String("good");
    char[] ch = {'t', 'e', 's', 't'};

    public void change(String str, char[] ch) {
        str = "test ok";
        ch[0] = 'b';
    }

    public static void main(String[] args) {
        StringExer e = new StringExer();
        e.change(e.str, e.ch);
        System.out.println(e.str); // good
        System.out.println(e.ch);  // best
    }
}
  • 通過字面量的方式(區別於new)給一個字符串賦值,此時的字符串值聲明在字符串常量池中。

字符串拼接操作

  • 常量與常量的拼接結果在常量池,原理是編譯期優化。
  • 常量池不會存在相同內容的常量。
  • 只要其中有一個是變量,結果就在堆中。變量拼接的原理是StringBuilder。(jdk1.5以前是StringBuffer)
  • 如果拼接的結果調用intern()方法,則主動將常量池中還有沒有的字符串對象放入池中,並返回此對象地址。
package com.chinda.java.base;

import org.junit.Test;

/**
 * @author Wang Chinda
 * @date 2020/5/30
 * @see
 * @since 1.0
 */
public class StrJoin {

    @Test
    public void test1() {
        String s1 = "javaEE";
        String s2 = "hadoop";
        String s3 = "javaEEhadoop";
        // 編譯器優化
        String s4 = "javaEE" + "hadoop";
        // 用變量做拼接,相當於在堆中new String()
        String s5 = s1 + "hadoop";
        String s6 = "javaEE" + s2;
        String s7 = s1 + s2;
        String s8 = s7.intern();

        // 編譯期優化。 相當於String s4 = "javaEEhadoop";
        System.out.println("s3 == s4 --> " + (s3 == s4));
        System.out.println("s3 == s5 --> " + (s3 == s5));
        System.out.println("s3 == s6 --> " + (s3 == s6));
        System.out.println("s3 == s7 --> " + (s3 == s7));
        // 將s7放入字符串常量池,但此時常量池中已經存在該常量,直接返回該常量的地址,即s3的地址賦值給s8
        System.out.println("s3 == s8 --> " + (s3 == s8));
        System.out.println("s5 == s6 --> " + (s5 == s6));
        System.out.println("s5 == s7 --> " + (s5 == s7));
    }
}

intern()在jdk1.6、jdk1.7、jdk1.8中的區別

    public static void main(String[] args) {
        String s3 = new String("1") + new String("1");
        s3.intern();
        String s4 = "11";
        System.out.println("s3 == s4 --> " + (s3 == s4));
    }

jdk1.6中為false,jdk1.7、jdk1.8中是true。

jdk1.6 JMM

jdk1.6

jdk1.8 JMM

jdk1.8


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM