我看JAVA 之 String
注:基于jdk11
String
在java語言中用來表示字元串,所有的字元串(比如“abc”)都String的執行個體對象。
String是常量,一旦建立不可以被修改,可以使用StringBuffer建立可變字元串。
String類提供了字元串比較,查找,拷貝,大小寫轉換等操作。大小寫轉換基于标準的Unicode.
字元串拼接”+”:根據不同版本的jdk會有不同實作,如StringBuilder、StringBuffer、StringConcatFactory(invokeDynamic)
實作了如下接口
1. java.io.Serializable
2. Comparable<String>
3. CharSequence 提供對字元數組多種隻讀形式的統一通路方法規範
幾個重點的成員變量
/**
* jdk9開始使用byte[]存儲字元串,1.8及之前使用char[]儲存
*/
@Stable
private final byte[] value;
/**
* coder用來表示此字元串使用的編碼,coder=0使用LATIN1,coder=1使用UTF16
*
* LATIN1 是8比特的字元集,定義了256個字元。前128個字元與ASCII完全一緻,即為ASCII的超集
* UTF16 是可變長度編碼。可以是一個或二個16比特。
* 根據不同的編碼由不同的工具類實作String的内部編碼,Latin1對應StringLatin1,UTF16對應StringUTF16
*
*/
private final byte coder;
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
/**
* 如果關閉壓縮,字元串的bytes使用UTF16編碼
*
* 如下為jit優化方面,為什麼不直接初始化COMPACT_STRINGS的值:
*
* The instance field value is generally opaque to optimizing JIT
* compilers. Therefore, in performance-sensitive place, an explicit
* check of the static boolean {@code COMPACT_STRINGS} is done first
* before checking the {@code coder} field since the static boolean
* {@code COMPACT_STRINGS} would be constant folded away by an
* optimizing JIT compiler. The idioms for these cases are as follows.
*
* For code such as:
*
* if (coder == LATIN1) { ... }
*
* can be written more optimally as
*
* if (coder() == LATIN1) { ... }
*
* or:
*
* if (COMPACT_STRINGS && coder == LATIN1) { ... }
*
* An optimizing JIT compiler can fold the above conditional as:
*
* COMPACT_STRINGS == true => if (coder == LATIN1) { ... }
* COMPACT_STRINGS == false => if (false) { ... }
*
* @implNote
* The actual value for this field is injected by JVM. The static
* initialization block is used to set the value here to communicate
* that this static final field is not statically foldable, and to
* avoid any possible circular dependency during vm initialization.
* 事實上,COMPACT_STRINGS的值是由JVM填充的
*/
static final boolean COMPACT_STRINGS;
static {
COMPACT_STRINGS = true;
}
/**
* Class String is special cased within the Serialization Stream Protocol.
*
* A String instance is written into an ObjectOutputStream according to
* <a href="{@docRoot}/../specs/serialization/protocol.html#stream-elements">
* Object Serialization Specification, Section 6.2, "Stream Elements"</a>
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
@Native static final byte LATIN1 = 0;
@Native static final byte UTF16 = 1;
幾個重要的方法
1. getBytes()相關
/**
* getBytes() 将目前字元串轉換為目前檔案系統預設編碼格式的位元組數組
* getBytes(charset) 将目前字元串轉換為指定編碼格式的位元組數組
*/
public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null) throw new NullPointerException();
return StringCoding.encode(charsetName, coder(), value);
}
public byte[] getBytes(Charset charset) {
if (charset == null) throw new NullPointerException();
return StringCoding.encode(charset, coder(), value);
}
public byte[] getBytes() {
return StringCoding.encode(coder(), value);
}
2. length()
/**
* 傳回目前字元串長度,如果是LATIN1字元串長度等于LATIN1格式位元組數組長度,否則需要取value.length>>1,長度減半
*/
public int length() {
return value.length >> coder();
}
3. native intern()
/**
* 當調用intern方法時,如果常量池中已經存在equal目前String的對象,那麼傳回String常量池中的字元串。
* 否則,目前String對象會被添加到String常量池并且傳回常量池中的String對象引用
* 如果a.intern() == b.intern(),那麼a.equal(b) == true
*/
public native String intern();
幾個重要的工具類
1. StringLatin1 提供了啟用壓縮編碼Latin1的情況下的一些常用操作如indexOf、hashcode、replace、trim、strip、compare等
2. StringUTF16 提供了編碼為UTF16的情況下的一些常用操作如indexOf、hashcode、replace、trim、strip、compare等
3. StringCoding 提供了為String編解碼decode & encode操作