1. Introduction to String, common methods source code analysis
2. String constant pool analysis
Common methods
equals
trim
replace
concat
split
startsWith and endsWith
Substring
toUpperCase() and toLowerCase()
compareTo
Introduction to String
The String class is modified by final, which means that the String object is an immutable, and concurrent programs prefer immutables. The String class implements the Serializable, Comparable, and CharSequence interfaces.
Start with a piece of code:
public void stringTest(){ String a = "a"+"b"+1; String b = "ab1"; System.out.println(a == b);}Guess what the result is? If your conclusion is true. OK, let's have another code:
public void stringTest(){ String a = new String("ab1"); String b = "ab1"; System.out.println(a == b);}What is the result? The correct answer is false.
Let's see how the code compiled by the compiler
//The first code public void stringTest() { String a = "ab1"; String b = "ab1"; System.out.println(a == b);} //The second code public void stringTest() { String a1 = new String("ab1"); String b = "ab1"; System.out.println(a1 == b);}In other words, the first piece of code has been optimized during the compilation period because the compiler found that the effects of "a"+"b"+1 and "ab1" are the same, and they are both composed of immutables. But why are their memory addresses the same? If you are still interested in this, let’s take a look at some important source codes of the String class.
Source code
1. String attributes
The String class contains an immutable char array to store strings, and an int variable hash is used to store the calculated hash value.
/** The value is used for character storage. */private final char value[];/** 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;
2. String constructor
//Constructors without parameters are generally useless, because value is an immutable public String() { this.value = new char[0];}//The parameter is String type public String(String original) { this.value = original.value; this.hash = original.hash;}//The parameter is a char array, use the Arrays class in the java.utils package to copy public String(char value[]) { this.value = Arrays.copyOf(value, value.length);}// Start from the offset position in the bytes array, encode the bytes of length in the charsetName format and copy it to valuepublic String(byte bytes[], int offset, int length, String charsetName) throws UnsupportedEncodingException { if (charsetName == null) throw new NullPointerException("charsetName"); checkBounds(bytes, offset, length); this.value = StringCoding.decode(charsetName, bytes, offset, length);}//Call the public String(byte bytes[], int offset, int length, String charsetName) constructor public String(byte bytes[], String charsetName) throws UnsupportedEncodingException { this(bytes, 0, bytes.length, charsetName);}3. Common methods of String
1. equals
boolean equals(Object anObject)public boolean equals(Object anObject) { //If the reference is the same object, return true if (this == anObject) { return true; } //If data of type String is not String, return false if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; //If the length of the char array is not equal, return false if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; //Judge from the single character back to the front, if there is any inequality, return false while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } //Each character is equal, return true return true; } } return false;}String e1 = "good";String e2 = "good everyDay";e1.equals(e2); // Return false
1 First, determine whether the same object is referenced ==, that is, determine whether the memory addresses of the two references are the same. If the same, it will directly return true.
2 Will determine whether the types are the same and whether they are the same data type
3 If the same type is used, the length of the converted character array is the same.
4 Compare whether each character is the same from the back to the front
Judgment order =》 1. Memory address 2. Data type 3. Character array length 4. Single character comparison
2. compareTo
int compareTo(String anotherString)public int compareTo(String anotherString) { //The length of the string of the own object len1 int len1 = value.length; //The length of the string of the compared object len2 = anotherString.value.length; //The minimum value of the length of two strings lim int lim = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value; int k = 0; //From the first character of the value to the minimum length lim, if the characters are not equal, return itself (characters where the objects are not equal - the characters that are compared) while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } //If the fronts are all equal, return (itself length - length of the object being compared) return len1 - len2;}String co1 = "hello" ;String co2 = "hello";String co3 = "hello you"; System.out.println(co1.compareTo(co2)); // 0System.out.println(co1.compareTo(co3)); // -4
This method is written ingeniously, and you can judge the character size from 0 first.
If the comparison between the two objects can compare characters is still equal, then the length of the object being compared is directly returned. If the length of the two strings is equal, then the return is 0, which cleverly judges the three situations.
3.hashCode
int hashCode()public int hashCode() { int h = hash; //If the hash has not been calculated and the string is not empty, then hashCode calculation is performed if (h == 0 && value.length > 0) { char val[] = value; //Computation process//s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } //hash assignment hash = h; } return h;}String a = "toyou";char val[] = a.toCharArray();char c1 = 't';char c2 = 'a';int f = c1; int e = c2; System.out.println(e); // 97 aSystem.out.println(f); // 116 tSystem.out.println(31*val[0]); // 3596System.out.println(31*c1); // 3596// hashCode calculation because char characters can be automatically converted into the corresponding int shaping
The String class overrides the hashCode method, and the hashCode method in Object is a Native call.
The hash of the String class is calculated using polynomials. We can completely obtain the same hash through different strings. Therefore, the hashCode of two String objects is the same, which does not mean that the two Strings are the same.
The hashCode of the same String object must be the same, but the hashCode is the same, not necessarily the same object
4.startsWith
boolean startsWith(String prefix,int toffset)public boolean startsWith(String prefix, int toffset) { char ta[] = value; int to = toffset; char pa[] = prefix.value; int po = 0; int pc = prefix.value.length; // Note: toffset might be near -1>>>1. //If the starting address is less than 0 or (starting address + length of the compared object) is greater than the length of the own object, return false if ((toffset < 0) || (toffset > value.length - pc)) { return false; } //Compare from the end of the object being compared while (--pc >= 0) { if (ta[to++] != pa[po++]) { return false; } } return true;}public boolean startsWith(String prefix) { return startsWith(prefix, 0);}public boolean endsWith(String suffix) { return startsWith(suffix, value.length - suffix.value.length);} String d = "www.58fxp.com"; System.out.println(d.startsWith("www")); // true System.out.println(d.endsWith("com")); // trueStarting and ending comparison are common methods. For example, when judging whether a string is from http protocol, or initially judging whether a file is an mp3 file, you can use this method to compare.
5.concat
String concat(String str)public String concat(String str) { int otherLen = str.length(); //If the added string is empty, return the object itself if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true);} String cat = "much"; String newcat = cat.concat(" yes"); // much yesThe concat method is also one of the commonly used methods. It first determines whether the added string is empty to decide whether to create a new object.
1 If the spliced character length is 0, return directly to the original character object
2 The spliced characters are not empty and return a new character object
Determine the character length to generate a new object
6.replace
String replace(char oldChar,char newChar)public String replace(char oldChar, char newChar) { //Compare the old and new values first if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */ // Find the position where the old value first appears while (++i < len) { if (val[i] == oldChar) { break; } } //From that position, until the end, replace the old value that appears with the new value if (i < len) { char buf[] = new char[len]; for (int j = 0; j < i; j++) { buf[j] = val[j]; } while (i < len) { char c = val[i]; buf[i] = (c == oldChar) ? newChar : c; i++; } return new String(buf, true); } } return this;} String r1 = "how do you do"; String r2 = r1.replace("do","is");System.out.println(r2); // how is you isThis method also has some cleverness, such as finding out where the old value appears at the beginning, which saves some comparison time.
The replace(String oldStr,String newStr) method is judged by regular expressions.
7.trim
String trim()public String trim() { int len = value.length; int st = 0; char[] val = value; /* avoid getfield opcode */ // Find the position without spaces in front of the string while ((st < len) && (val[st] <= ' ')) { st++; } // Find the position without spaces at the end of the string while ((st < len) && (val[len - 1] <= ' ')) { len--; } //If there are no spaces in front and after, return the string itself ((st > 0) || (len < value.length)) ? substring(st, len) : this;} String t1 = " public void "; // One space in front and after System.out.println("t1:"+t1.length()); // 13 With space length String t2 = t1.trim(); System.out.println("t2:"+t2.length()); // 11 Remove the space System.out.println(t2);8.intern
String intern()public native String intern();
String dd = new String("bb").intern();The ntern method is a Native call, and its function is to find objects of equal value through the equals method in the constant pool in the method area.
If not found, open a space in the constant pool to store the string and return the reference to the corresponding String. Otherwise, directly return the reference to the String object already exists in the constant pool.
You can also force the character object created for the new method to see if the constant pool already exists.
Put the second code in the introduction
//String a = new String("ab1");//Change to String a = new String("ab1").intern();The result is true, because the address pointed to by a comes from the constant pool, and the string constant pointed to by b will call this method by default, so a and b both point to the same address space.
int hash32()private transient int hash32 = 0;int hash32() { int h = hash32; if (0 == h) { // harmless data race on hash32 here. h = sun.misc.Hashing.murmur3_32(HASHING_SEED, value, 0, value.length); // ensure result is not zero to avoid recalcing h = (0 != h) ? h : 1; hash32 = h; } return h;}In JDK1.7, when the String class is used as a key, the Hash-related collection class no longer uses the hashCode method to discrete data, but uses the hash32 method.
This method uses the system's current time, String class address, System class address, etc. as factors to calculate the hash seed. Through the hash seed, a 32-bit int value is obtained through the hash seed.
public int length() { return value.length;}public String toString() { return this;}public boolean isEmpty() { return value.length == 0;}public char charAt(int index) { if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return value[index];}The above are some simple common methods.
Summarize
String objects are immutable types. String methods with return type String return each time a new String object is returned, except for certain specific conditions of some methods to return itself.
Three ways to compare String objects:
==Memory comparison: Directly compare the memory values pointed to by the two references, which are accurate, concise, and straightforward.
equals string value comparison: Compare whether the literal values of the two referenced objects are equal.
Comparison of hashCode string numericalization: numericalization of strings. The two referenced hashCodes are the same, and the memory is not guaranteed to be the same, and the literal values are not guaranteed to be the same.
Design idea of string constant pool
1. Original intention of string constant pool design
Each string is a String object, and strings will be frequently used in system development. If created and destroyed like other objects, it will greatly affect the performance of the program.
In order to improve performance and reduce memory overhead, JVM optimizes when instantiating strings.
A string constant pool is opened for strings, similar to a cache area
When creating a string constant, first determine whether the string constant pool exists.
The string returns a referenced instance, does not exist, instantiate the string, and put it in the pool.
Realize the basics
The basis for implementing this optimization is that each string constant is a final modified constant, so there is no need to worry about data conflicts in the constant pool.
There is a table in the global string constant pool created by the runtime instance, which always maintains a reference for each unique string object in the pool, which means that they always refer to objects in the string constant pool, so these strings in the constant pool will not be collected by the garbage collector.
Heap, stack, method area
Understanding string constant pools, first look at the stack method area
heap
What is stored is an object, each object contains a corresponding class
The JVM only has one heap area and is shared by all threads. There are no basic types and object references in the heap, but only the object itself
Objects are collected by the garbage collector, so the size and life cycle need not be determined
Stack
Each thread contains a stack area, which only stores basic data type objects and custom object references.
The data (primitive type and object reference) in each stack are private
The stack is divided into three parts: the basic type variable area, the execution environment context, and the operation instruction area (storing operation instructions)
The data size and life cycle are certain, and when no reference points to this data, the data will disappear.
Method area
Static zones, like heaps, are shared by all threads
The method area contains elements that are always unique in the entire program, such as class and static variables;
String constant pool
String constant pool exists in the method area
Code: Stack method area stores strings
String str1 = "abc";String str2 = "abc";String str3 = "abc";String str4 = new String("abc");String str5 = new String("abc");Interview questions
String str4 = new String("abc") How many objects are created?
Split: str4 = , new String(), "abc"
You can create a new object through new method. The new method creates an instantiated object and will not go to the constant pool to find whether it already exists. As long as new, a new object will be instantiated.
"abc" Each string is a String object. If there is no in the constant pool, a new object will be created and put into the constant pool. Otherwise, the object reference will be returned.
Assign the object address to str4 and create a reference
So, if there is no "abc" literal in the constant pool, create two objects, otherwise create one object, and create a reference
String str1 = new String("A"+"B"); How many objects will be created? String str2 = new String("ABC") + "ABC"; How many objects will be created?
The above comprehensive analysis of the java String source code and String constant pool is all the content I share with you. I hope you can give you a reference and I hope you can support Wulin.com more.