字符序列(CharSequence)


字符序列(CharSequence)

1、相關接口

 

  • java.lang.CharSequence 接口

  • java.lang.Appendable接口

  • java.lang.Comparable接口

  • java.io.Seralization 接口

2、java.lang.String

 

2.1、概念:String 是個類 character strings 才是字符串

1、在 Java 語言中 直接使用 “” 引起來的多個字符就是 字符串 (character strings) 2、在 Java 源代碼中 直接使用 “” 引起來的字符串 都是 java.lang.String 的實例 3、String 類 是個 不可變類 將來創建的 每個 String 實例 都是不可變的對象【Strings are constant】

[Java 8及之前] public final class String { private char[] value; // 使用 char 數組保存字符序列 }

[Java 9 之后] public final class String { private final byte[] value; // 使用 byte 數組保存字節序列 } 字節序列是字符序列根據某種編碼轉換而來

通過 "" 雙引號來創建字符串

java.lang.String 類的主要字段 Java 11

 public final class String implements Serializable, Comparable<String>, CharSequence {
     
     private final byte[] value;
     private final byte coder;
     private int hash;
     
     
     public String(String original) {
         this.value = original.value;
         this.coder = original.coder;
         this.hash = original.hash;
    }
     
 }

 

String t = new String("abc123");

 

首先通過 "abc123" 來創建 String 的實例

這個實例在 String 常量池中

 // 三個字段
 byte[] value:0xA1B2C3 // 通過創建堆內存的 byte[] 來存取 "abc123" 數組變量value 存放數組的引用
 byte coder:0
 int hash:-1424436592

 

堆內存的 byte[]

 {97,98,99,49,50,51} // 假設地址為 0xA1B2C3

 

當我們在堆內存中 new String( s ) 這時調用 String 類的構造方法

 public String(String original) {
     this.value = original.value;
     this.coder = original.coder;
     this.hash = original.hash;
 }

將 常量池的值復制一份過來

但 String t = new String("abc123");

變量 t 存放的是 一個堆中的地址

如果 String s1 = "abc123"; 和 String s2 = "abc123";

這里的 s1 和 s2 存放的是常量池實例的地址 是相同的

2.2、new String( s ) 的內存圖

 

image-20200529115916201

 

但凡是出現了 "" 引起來的內容,這部分內容一定放在 String 常量池中

String t = new String("abc123");

創建一個 “abc123” 對應 String 實例 並添加到常量池中

在堆內存創建 String 實例 並將 "abc123" 的 value / hash / coder 拷貝到新創建的 String 實例中

 

3、String 的部分實例變量

  • private final byte coder;

  • private int hsah;

  • private final byte[] value;

 

4、String 內部的一些方法

構造方法

  • public String(byte[] bytes)

  • public String(byte[] bytes, int offset, int length)

  • public byte[] getBytes()

等等一些重載方法

類變量

  • static final byte LATIN1 = 0;

  • static final byte UTF-16 = 1;

類方法

  • valueOf()

     將 基本數據類型的值 轉化為 字符串形式 valueOf(boolean|int|long|float|double|char)
  • format

  • join

實例方法

 

1、char charAt(int) 獲取指定索引的單個字符 2、int length() 獲取字符串長度 3、public boolean contains(CharSequence s) 判斷指定的字符序列是否存在於 當前字符串中 4、int indexOf(int ch) 查詢指定字符 在當前字符串中 首次出現的位置 存在返回索引 不存在 -1 5、int indexOf(String s) 6、int lastIndexOf(int ch) 7、int lastIndexOf(String s)

 

 package CharSequence;
 /**
  * 1、char charAt(int) 獲取指定索引的單個字符
  * 2、int length() 獲取字符串長度
  * 3、public boolean contains(CharSequence s) 判斷指定的字符序列是否存在於 當前字符串中
  * 4、int indexOf(int ch) 查詢指定字符 在當前字符串中 首次出現的位置 存在返回索引 不存在 -1
  * 5、int indexOf(String s)
  * 6、int lastIndexOf(int ch)
  * 7、int lastIndexOf(String s)
  * */
 public class StringTestA {
    public static void main(String[] args) {
 
        final String s = "今天天氣好晴朗處處好風光好風光";
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            System.out.print(ch);
            System.out.print(i<s.length() - 1 ? "," : "\n");
        }
        // 因為 String 類實現了 CharSequence接口
        CharSequence cs = "好風光"; // 所以用 CharSequence 類型的引用變量指向了 String 實例是可以的
        boolean z = s.contains(cs);
        System.out.println(z);
 
        // 整個字符串中的每個字符的索引 一樣 從 ”左“ 開始統計 與數組相同
        int index = s.indexOf('天');// 獲取 天 在變量 s 所指向的字符串首次出現的位置(索引)
        System.out.println(index);
 
        index = s.indexOf("好風光");
        System.out.println(index); // 獲取 好風光 在變量 s 所指向的字符串首次出現的位置(索引) 好的位置
 
        int lastIndex = s.lastIndexOf('天'); // 獲取 天 在變量 s 所指向的字符串最后出現的位置(索引)
        System.out.println(lastIndex);
 
        lastIndex = s.lastIndexOf("好風光"); // 獲取 好風光 在變量 s 所指向的字符串最后出現的位置(索引) 還是好的位置
        System.out.println(lastIndex);
 
    }
 }
 

 

indexOf( int ch , int from )

int indexOf( String s , int from )

int lastIndexOf( int ch , int from )

int lastIndexOf( String s , int from )

 package CharSequence;
 
 /**
  * 1、 int indexOf( int ch , int from )
  * 從 當前字符串中 指定位置(from) 開始尋找 指定字符 ( ch ) 首次出現的位置,若存在即返回該索引,否則返回 -1
  * 2、int indexOf( String s , int from )
  * 從 當前字符串中 指定位置(from) 開始尋找 指定字符串 ( s ) 首次出現的位置,若存在即返回該索引,否則返回 -1
  * 3、int lastIndexOf( int ch , int from )
  * 從 當前字符串中 指定位置(from) 開始反向尋找 指定字符 ( ch ) 最后一次出現的位置,若存在即返回該索引,否則返回 -1
  *         即獲取在 from 處及其之前 ch 最后一次出現的位置是什么
  *         ( 反向尋找的順序是 from 、from - 1 、from - 2 、........ )
  * 4、int lastIndexOf( String s , int from )
  * 從 當前字符串中 指定位置(from) 開始反向尋找 指定字符串 ( s ) 最后一次出現的位置,若存在即返回該索引,否則返回 -1
  * 即獲取在 from 處及其之前 s 最后一次出現的位置是什么
  */
 public class StringTestB {
 
  public static void main(String[] args) {
 
  final String s = "http://www.ecut.edu.cn:8080/soft/java/beginner/string/test.html" ;
 
  int index ;
  int last ;
 
  index = s.indexOf( '/' ) ;
  last = s.lastIndexOf( '/' );
  System.out.println( index + " , " + last );
 
  System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
 
  index = s.indexOf( '/' , 10 ); // 從 索引 10 開始 向后尋找 '/' 字符首次出現的位置
  last = s.lastIndexOf( '/' , 37 ); // 從 索引 37 處開始 反向尋找 '/' 字符 最后一次出現的位置
  System.out.println( index + " , " + last );
 
 
 
  }
 
 }
 

 

 

1、String concat(String) 將當前字符串 與 參數給定的字符串拼接起來 並返回一個新的 字符串 2、String toUpperCase() 3、String toLowerCase() 4、equalsIgnoreCase() 忽略大小寫 5、a.contentEquals(b) 用於比較參數指定的 字符序列 是否與當前String

 

 package CharSequence;
 /**
  * 1、String concat(String) 將當前字符串 與 參數給定的字符串拼接起來 並返回一個新的 字符串
  * 2、String toUpperCase()
  * 3、String toLowerCase()
  * 4、equalsIgnoreCase() 忽略大小寫
  * 5、a.contentEquals(b) 用於比較參數指定的 字符序列 是否與當前String
  */
 
 public class StringTestC {
     public static void main(String[] args) {
         String s = "abc";
 
         String x = s.concat("123");
         System.out.println(s); // "abc"
         System.out.println(x); // "abc123"
 
         System.out.println("~~~~~~~~");
 
         String t = s.toUpperCase();
 
         final String a = "hello";
         final String b = "Hello";
 
         System.out.println(a.equals(b)); // String 重寫后的 equals 比較大小
         System.out.println(a.equalsIgnoreCase(b)); // true 忽略大小寫
         System.out.println(a.contentEquals(b)); // 區分大小寫
 
         System.out.println("~~~~~~~~~~~~");
         // 用於比較兩個字符串的 “大小”
         System.out.println(a.compareTo(b)); //
         // 相等 返回 0 否則 非0整數
         System.out.println(a.compareToIgnoreCase(b)); //
    }
 }
 

 

1、int length() boolean isEmpty() 是否為空 value.length 是否為0 boolean isBlank() 用於判斷 是否為空 (空白 僅僅包含了 空格 tab 等字符) String trim() 剔除首尾空白 不包括 中間的空白

 

 package CharSequence;
 /**
  * 1、int length()
  * boolean isEmpty() 是否為空 value.length 是否為0
  * boolean isBlank() 用於判斷 是否為空 (空白 僅僅包含了 空格 tab 等字符)
  * String trim() 剔除首尾空白 不包括 中間的空白
  * */
 public class StringTestD {
     public static void main(String[] args) {
 
         String s = ""; // 空串 不是 空格 不是 制表符(Tab) 也不是 null 和 /u0000
         System.out.println(s);
         System.out.println("length:" + s.length());
         System.out.println("empty:" + s.isEmpty());
 
         System.out.println("~~~~~~~~~~~~~~");
         String t = "           "; // 有空格 和 tab
         System.out.println("length:" + s.length());
         System.out.println("empty:" + s.isEmpty());
         System.out.println("is blank" + t.isBlank());
 
         String x = "   ecut ";
         String trim = x.trim(); // 刪除首尾空白 不包括中間的空白返回新的 String 實例
         System.out.println(x.length());
         System.out.println(trim.length());
 
    }
 }
 

1、boolean startsWith(String) 對應的字符串 是否以 參數 字符串 開始

2、boolean endsWith(String) 對應的字符串 是否以 參數 字符串 結束

 

 package CharSequence;
 
 import java.util.Arrays;
 
 /**
  * 1、boolean startsWith(String) 對應的字符串 是否以 參數 字符串 開始
  * 2、boolean endsWith(String) 對應的字符串 是否以 參數 字符串 結束
  *
  * */
 
 public class StringTestE {
    public static void main(String[] args) {
 
        String path = "D:/java-beginner/char-sequence/StringHelper.java";
 
        System.out.println(path.startsWith("D:")); // true path 對應的字符串 是否以 D: 開始
        System.out.println(path.endsWith(".java")); // true
        System.out.println("~~~~~~~~~~~");
 
        System.out.println(path.startsWith("/",10)); // 從 10 開始 是否 是 以 / 開始的
 
 
        char[] array = new char[10];
        String str = "滄海一聲笑滔滔兩岸潮";
        // 將 str 所指向的 String 實例中 所包含的字符串[5,10) 之間的字符 拷貝到 數組 array 中
        str.getChars(5,10,array,5);
        System.out.println(Arrays.toString(array));
 
        String substring = str.substring(5); // [5,length() - 1]
        System.out.println(substring);
 
    }
 }

 

5、代碼解釋 String 實例的創建過程

 

 package CharSequence;
 /**
  * 1、在 Java 語言中 直接使用 “” 引起來的多個字符就是 字符串 (character strings)
  * 2、在 Java 源代碼中 直接使用 “” 引起來的字符串 都是 java.lang.String 的實例
  * 3、String 類 是個 不可變類 將來創建的 每個 String 實例 都是不可變的對象【Strings are constant】
  *
  *   [Java 8及之前]
  *   public final class String {
  *       private char[] value; // 使用 char 數組保存字符序列
  *   }
  *
  *   [Java 9 之后]
  *   public final class String {
  *       private final byte[] value; // 使用 byte 數組保存字節序列
  *   }
  *   字節序列是字符序列根據某種編碼轉換而來
  *
  * */
 
 public class StringTest2 {
     public static void main(String[] args) {
 
         // 變量 s 直接引用了 字符串常量池中的 String實例
         String s = "中國是世界上最偉大的國家,沒有之一";
         // 變量 t 引用的是在 堆內存重新創建的 String 實例
         String t = new String("中國是世界上最偉大的國家,沒有之一");
 
         System.out.println(s == t);
         System.out.println(s.equals(t)); // true String 重寫后的 equals
 
    }
 }
 

 

6、編碼 和 解碼

編碼(encode):將字符串按照某種字符集 轉換成字節序列

例如:比如 “中國”==UTF-8==>{-28, -72, -83, -27, -101, -67}

解碼( decode ):將字節序列按照某種字符集 轉換成字符串

例如:比如 {-28, -72, -83, -27, -101, -67}==UTF-8==>“中國”

7、常用字符集

  • ISO-8859-1 別名:LATIN1

  • Big5:繁體中文

  • GBK:簡體中文 每個字符占兩個字節

Unicode:萬國碼

  • 范圍是 U+0000-U+10FFFF

  • Java 語言中 char 類型的范圍:U+0000-U+FFFF

  • UTF-8

    • UTF-8 是 Unicode 的一種可變長字符編碼

    • 將字符串中的字符編碼為字符序列后 每個字符占用 1 - 4個字節

    • 漢字節本都占用 3 個字節

    • 8位元指的是一個單位為 8 位

  • UTF-16

    • UTF-16

    • UTF-16BE

    • UTF-16LE

  • UTF-32

    • UTF-32

    • UTF-32BE

    • UTF-32LE

8、String 內部的 byte 數組編碼格式

 

 package CharSequence;
 
 import java.nio.charset.Charset;
 import java.util.Arrays;
 /** 1、在 String 實例內部封裝的 byte 數組中存儲的字節序列是字符串 按照 UTF-16LE 編碼 編碼后的字節序列
  * 2、在通過 String 實例的 getBytes 方法獲取字節序列時,可以確定任意字符集
  * 3、將一組字節序列構成 String 實例時 必須指定 將 字符串編碼為字節序列時所采用的的字符串 才能保證不亂碼
  *
  * */
 public class StringTest9 {
     public static void main(String[] args) {
         final String s = "中國威武";
 
         StringHelper.perspective(s);
         System.out.println("~~~~~~~~~~~");
         Charset utf = Charset.forName("UTF-16LE"); // 16 bit
 
         byte[] bytes = s.getBytes(utf); // UTF-16
         System.out.println(Arrays.toString(bytes));
 
         byte[] array = {45, 78, -3, 86, 1, 90, 102, 107};
         String x = new String(array,utf); //不使用 UTF-16LE 會亂碼
         System.out.println(x);
 
 
    }
 }
 

 

 


免責聲明!

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



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