Limited level , Where there is a mistake, we need criticism and correction .

The article explains from two aspects ,1, introduce ,2, Source code analysis

String Class represents java String in ,

One ,String introduce

1, Immutable class , Thread safety .

Immutable classes in java Use in language final Keyword implementation ,final There are three functions , Simply put, the modified class is not inheritable , Method cannot be overridden , Variable cannot be modified . and String Class and for storing character data Char Array is just using final Decorated , therefore string Class is not inheritable , internal data (char array ) Cannot be modified , Yes String Replace , Crop , All connections are newly generated String object , therefore String Is immutable , Immutable classes are thread safe , The most typical is JAVA Packaging class in Integer,Long etc . Why are immutable classes thread safe ? because String Object is stateless , Stateless objects can be understood as objects whose state cannot be changed , The state here can also be understood as the data in the object .

2, Shareable

jdk7 The runtime constant pool is stored in the method area , Permanent generation (hotspot),jdk8 Permanent generation removed , The runtime constant pool is stored in the Metaspace of local memory , The runtime constant pool stores references to string constants , String constants are stored in the heap .java Using constant pool to realize string sharing , Let's take a look at an example
public static void main(String[] args) { String a = "test"; String b =
"test"; System.out.println(a == b); String c = new String("test");
System.out.println(a == c); }

The result is a true, One false.a and b Both point to references in the constant pool , So they have the same address ,a==b That's why true, and c Points to a reference to a newly created object on the heap , and a Not pointing to the same string address , therefore a==c by false,javap Corresponding instructions

Let's take a look at the places where the lines are drawn , First place from top to bottom , Second division , The fourth is to get character transfer from constant pool test References to , And the third is new Reference returned , therefore a and b Same address ,a,b and c The address of is different .

3, Simple and efficient

The most common operation in the program is string splicing ,java Can be used directly in + Operator to represent string concatenation , Let's look at the following code .
public static void main(String[] args) { String s1 = "a"; String s2 = "b";
String s3 = s1 + s2 + "c"; System.out.println(s3); }
View compiled instructions

1, Create a StringBuilder object

2, call StringBuilder Constructor for

3,3,4,5 All steps are called StringBuilder Of append Method will s1,s2, and "c" Splicing .

conclusion : character string + Operational quilt java Compiler compiles to create a new one StringBuilder object , And then each + Will be compiled into append method , So we can use it directly in general + Concatenate string ,java Why do you do that , Because of performance , If not used StringBuilder The splicing process will produce a lot of middle String object . Of course, in some cases, you need to use it explicitly StringBuilder, Look at the following code .
public static void main(String[] args) { String s1 = "a"; for (int i = 0; i <
10; i++) { s1 = s1 + i; } System.out.println(s1); }
  javap View instructions

1,1 Pop up the top two elements of the stack for comparison , If the second element is greater than or equal to the first element, jump to 36 Code division ,36 The code is the jump out for Cycle output result System.out Where , The first element that pops up in the stack is 10 The second is constant i( First in, then out ), explain i Greater than or equal to 10 Then the cycle ends .

2,2 and 3 Indicates creation StringBuilder object ,4,5 Represents a call append Splicing s1 and i

3,6 Indicates that the spliced results are stored in the index as 1 In local variables of

4,7 Indicates that the local variable is indexed to 2 Variable plus of 1 that is 1

5,8 Indicates jump to instruction 5 place , Make the next comparison and cycle

conclusion : After analyzing the instructions, we found that for Use in cycle + String splicing , Every time the compiler compiles, it will for Generate a StringBuilder object , Then call append Concatenate string , If for Too much circulation will produce a lot of StringBuilder object , Cause performance problems , So we're building outside the loop StringBuilder, Call in loop append operation , The code is simple, so we won't show it .

Two , Source code analysis

1,String Achieved Serializable,Comparable<String>,CharSequence representative String Is serializable , Comparable , Character sequence .

2, Main attributes

char value[] Character storage array

private int hash  hash value

static final Comparator<String> CASE_INSENSITIVE_ORDER Ignore case comparator

3, common method
int hashCode() Computing object's hashcode public int hashCode() { int h = hash; if (h == 0
&& value.length > 0) { //1 char val[] = value; for (int i = 0; i <
value.length; i++) { //2 h = 31 * h + val[i]; } hash = h; //3 } return h; //3 }
1, If h Not for 0 perhaps value The length of is 0 Then return directly h,h Not for 0 Description of h It has been calculated and returned directly , therefore hashCode Only once .

2, ergodic char Each character value in the array plus h*31, Every element in the array participates in the operation to make the result more accurate ,h*31 send hashcode Values are more dispersed , multiply 31 Can also be optimized for bit operation , Faster computing .

3, to h Return after assignment
static String join(CharSequence delimiter, CharSequence... elements)
elements use delimiter Back after splitting and splicing public static String join(CharSequence delimiter,
CharSequence... elements) { Objects.requireNonNull(delimiter); //1
Objects.requireNonNull(elements); //1 // Number of elements not likely worth
Arrays.stream overhead. StringJoiner joiner = new StringJoiner(delimiter); //2
for (CharSequence cs: elements) { //3 joiner.add(cs); } return
joiner.toString(); //4 }
1, Verify that the parameters are correct
2, Create separator as delimiter Of StringJoiner

3, Traversal variable length string parameter , Call for each string joiner.add,joiner.add Inside by a StringBuilder Of value attribute , every time add Will use value Add separator and then string ,value If it is blank, add prefix and string , No prefix here .
4, call joiner.toString() return , Return if no suffix value.toString, Otherwise, add the suffix and return toString, No suffix here  
static String format(String format, Object... args) public Formatter
format(Locale l, String format, Object ... args) { ensureOpen(); // index of
last argument referenced int last = -1; //1 // last ordinary index int lasto =
-1; //1 FormatString[] fsa = parse(format); //2 for (int i = 0; i < fsa.length;
i++) { FormatString fs = fsa[i]; int index = fs.index(); try { switch (index) {
case -2: // fixed string, "%n", or "%%" //3 fs.print(null, l); break; case -1:
// relative index //4 if (last < 0 || (args != null && last > args.length - 1))
throw new MissingFormatArgumentException(fs.toString()); fs.print((args == null
? null : args[last]), l); break; case 0: // ordinary index //5 lasto++; last =
lasto; if (args != null && lasto > args.length - 1) throw new
MissingFormatArgumentException(fs.toString()); fs.print((args == null ? null :
args[lasto]), l); break; default: // explicit index //6 last = index - 1; if
(args != null && last > args.length - 1) throw new
MissingFormatArgumentException(fs.toString()); fs.print((args == null ? null :
args[last]), l); break; } } catch (IOException x) { lastException = x; } }
return this; //7 }
1,last,lasto Both point to parameter index location .

2,parse(format) Parse string , Add the split normal string and format string to the FormatString[] in ,FormatString It's an interface , There are two implementation classes FixedString For normal string , Indexes index by -2,FormatSpecifier For formatted characters , Used to format parameters ,index There are three values ,0 For normal index , That is, formatting characters that do not specify the index location , for example %s,%d,-1 Represents relative position , take last The parameter of the location is formatted with this format character , for example %<s,%<d,
default Parameter representing an explicitly specified parameter index , for example %1$s,%2$s

3, ergodic FormatString,index by -2 Represents a normal string , Use directly Formatter Properties in a(StringBuilder) Splicing

4,index by -1, Format character use relative position , Use previous index last Parameter call for print Format , Formatted string usage properties a Splicing .

5,index by 0, Format character use order position ,lasto plus 1, The next parameter to the current location ,last assignment , Call to next location string print After formatting , use a Splicing

6,default, Format character use specified parameter location , use index-1 Parameter call to print format , Use after formatting a Splicing

7, return a.toString
String concat(String str) Current string concatenation str Returns the concatenated string public String concat(String
str) { int otherLen = str.length(); if (otherLen == 0) { //1 return this; } int
len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); //2
str.getChars(buf, len); //3 return new String(buf, true); //4 }
1, If the string parameter length is 0, Returns the current string directly .

2,Arrays.copyOf Create an array with the size of the current string plus the length of the parameter string , contain value Value of , Inside the method is a new size of len+otherLen Array of , Then call System.arraycopy take value The contents of the array are copied to the new array , And return the new array ,System.arraycopy It's a local approach , from c,c++ More efficient implementation .

3, take Str Array data of characters into new array len Beginning to len+Str.length place , Internal call System.arraycopy.

4, New string , Construct parameter as new array buf.
String[] split(String regex, int limit) according to regrex Delimited string ,limit Limit for number of delimited strings public
String[] split(String regex, int limit) { /* fastpath if the regex is a
(1)one-char String and this character is not one of the RegEx's meta characters
".$|()[{^?*+\\", or (2)two-char String and the first char is the backslash and
the second is not the ascii digit or ascii letter. */ char ch = 0; if
(((regex.value.length == 1 && ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) ==
-1) || (regex.length() == 2 && regex.charAt(0) == '\\' && (((ch =
regex.charAt(1))-'0')|('9'-ch)) < 0 && ((ch-'a')|('z'-ch)) < 0 &&
((ch-'A')|('Z'-ch)) < 0)) && (ch < Character.MIN_HIGH_SURROGATE || ch >
Character.MAX_LOW_SURROGATE)) //1 { int off = 0; //2 int next = 0; //2 boolean
limited = limit > 0; ArrayList<String> list = new ArrayList<>(); while ((next =
indexOf(ch, off)) != -1) { //3 if (!limited || list.size() < limit - 1) {
list.add(substring(off, next)); off = next + 1; } else { // last one //assert
(list.size() == limit - 1); list.add(substring(off, value.length)); off =
value.length; break; } } // If no match was found, return this if (off == 0)
//4 return new String[]{this}; // Add remaining segment if (!limited ||
list.size() < limit) //5 list.add(substring(off, value.length)); // Construct
result int resultSize = list.size(); if (limit == 0) { //6 while (resultSize >
0 && list.get(resultSize - 1).length() == 0) { resultSize--; } } String[]
result = new String[resultSize]; return list.subList(0,
resultSize).toArray(result); //7 } return Pattern.compile(regex).split(this,
limit); //1 }

1, judge regrex Is it a character string ,. And it's not $|()[{^?*+\\ One of the characters , Or a string with two characters. The first character is a backslash , The second character is not ascll Number or letter , Otherwise, regular expression processing is adopted

2,off Indicates the starting position of interception ,next Location of character matching ,limited Is there a limit on the number of delimited strings

3, call while loop , Where to find character matches , If the limit of the number of partitions is reached , Add remaining strings directly to list in , Otherwise, intercept off reach next String of , That is, the starting position or the string from the previous separator to the current separator .

3, If off by 0, Description no matching characters , Return string directly

4, Add the remaining string if there is no limit on the number of partitions or if the limit on the number of partitions is not reached

5, Remove trailing empty strings if there is no limit to the number of partitions ,4 Step may add an empty string

6, String list is converted to string array and returned .
String replace(char oldChar, char newChar) Replace all oldchar The characters are newChar public
String replace(char oldChar, char newChar) { if (oldChar != newChar) { //1 int
len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */
while (++i < len) { //2 if (val[i] == oldChar) { break; } } if (i < len) { char
buf[] = new char[len]; for (int j = 0; j < i; j++) { //3 buf[j] = val[j]; }
while (i < len) { //4 char c = val[i]; buf[i] = (c == oldChar) ? newChar : c;
i++; } return new String(buf, true); } } return this; }
1, Returns the current string if two characters are equal

2, Find the first oldChar and newChar Equal position i, newly build char Array will be less than i Characters in the new array

3, from i Start traversal , If i Subscript characters and oldChar equal , New array subscript i assignment newChar, Otherwise, the new array subscript assigns the original character .

4, Return to new String, Parameter array is new buf.
String substring(int beginIndex, int endIndex) intercept beginIndex reach endIndex String of
public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) {
//1 throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex >
value.length) { //1 throw new StringIndexOutOfBoundsException(endIndex); } int
subLen = endIndex - beginIndex; if (subLen < 0) { //1 throw new
StringIndexOutOfBoundsException(subLen); } return ((beginIndex == 0) &&
(endIndex == value.length)) ? this : new String(value, beginIndex, subLen); //2
}
1, Judge whether the parameters are legal

2, Direct call String Constructor for creating a new string , Use in constructor Arrays.copyOfRange Copy data .
String trim() Clear the space before and after the string public String trim() { int len = value.length; int
st = 0; char[] val = value; /* avoid getfield opcode */ while ((st < len) &&
(val[st] <= ' ')) { //1 st++; } while ((st < len) && (val[len - 1] <= ' ')) {
//2 len--; } return ((st > 0) || (len < value.length)) ? substring(st, len) :
this; //3 }
1, first while Loop index from 0 Start index with the first character not a space

2, the second while Loop index from len Start the first index that is not a space

3, Call if there is a space subString Returns the truncated string with the spaces removed , Otherwise, return the current string .

Other method codes are relatively simple , No more details , If you have time, you can have a look at it yourself .
public boolean startsWith(String prefix, int toffset) public boolean
endsWith(String suffix) lastIndexOf(int ch) public int indexOf(int ch) public
boolean equals(Object anObject)
The next article will explain StringBuilder and StringBuffer

Technology
©2019-2020 Toolsou All rights reserved,
CSS architecture design NOI2019 travels Detailed explanation ubuntu14.04 How to set static IP2019 Year end summary —— Second year of work Big data tells you , How tired are Chinese women java Simple lottery algorithm , luck draw DemoPYTHON Summary of final review Classical algorithm - recursion ( The case of raw rabbit )2021 year 1 Monthly programmer salary statistics , average 14915 element First knowledge python Skills summary