Get to know String
1. Create a string
Common ways to construct String
// 方式一
String str = "abcd";
// 方式二
String str2 = new String("abcd");
// 方式三
char[] array = {
'a', 'b', 'c'};
String str3 = new String(array);
Precautions:
String literal constants such as "hello" are of type String and
String is also a reference type.String str = "Hello";
The memory layout of such code is as follows
Since String is a reference type, the
memory layout for the following code is as shown in the figure
String str1 = "Hello";
String str2 = str1;
But although both str1 and str2 point to "hello", "modifying" str2 will not affect str1
str2 = "world";
System.out.println(str2);
// 执行结果
Hello
Referencing a pointer similar to the C language, but opening up a small memory space on the stack to save an address.
In fact, the code like str1 = "world" does not count as "modifying" the string, but makes the reference of str1 point to a new String object.
2. String comparison is equal
If there are two int type variables, you can use == to complete the judgment of their equality.
int x = 10 ;
int y = 10 ;
System.out.println(x == y);
// 执行结果
true
But String comparison using == is not comparing the contents of the string, but comparing whether two references point to the same object . Use two codes to illustrate:
Code 1
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2);
// 执行结果
true
Code 2
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2);
// 执行结果
false
Let's analyze the difference between the two ways of creating String.
Code 1 memory layout
We found that str1 and str2 point to the same object. At this time, such as "Hello" is a string constant in such a string constant pool of.
Regarding the string constant pool, string literal constants
such as "Hello" also require a certain amount of memory space to store. Such a constant has a characteristic, that is, it does not need to be modified. So if there are multiple references in the code that need to use "Hello", just refer to this location in the constant pool directly, and there is no need to store "Hello" twice in memory.
Code 2 memory layout
by String str1 = new String("Hello");
the String object created in this way is equivalent to the heap another opened up a space to store the value "hello", so the contents of str1 and str2 are not the same.
If you want to compare the contents of strings in Java, you must use the equals
methods provided by the String class .
Precautions for using equals
String str = new String("Hello");
// 方式一
System.out.println(str.equals("Hello"));
// 方式二
System.out.println("Hello".equals(str));
Both methods are possible, but we recommend method two more.
String str = null;
// 方式一
System.out.println(str.equals("Hello"));
// 执行结果 抛出java.lang.NullPointerException 异常
// 方式二
System.out.println("Hello".equals(str));
//执行结果:false
Note: "Hello" literal constants like this, in essence, is a String object, you can use
equals
such asString
object methods
3. String constant pool
In the above example, the two examples of operation of the String class, direct assignment and new
a newString
a) Direct assignment
String str1 = "hello" ;
String str2 = "hello" ;
String str3 = "hello" ;
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // true
System.out.println(str2 == str3); // true
The design of the String class uses a shared design pattern.
In fact, an object pool (string constant pool) is automatically maintained at the bottom of the JVM.
If the direct assignment mode is now used to instantiate an object of the String class, then the instantiated object (string content) will be automatically saved in this object pool.
If you continue to use the direct assignment mode to declare String objects next time, if there is specified content in the object pool at this time, it will be directly referenced.
If not, create a new string object and save it in the object pool for next use.
b) Adopt the construction method
It is standard practice for class objects to be instantiated using constructors. Analyze the following procedures:
String str = new String("hello");
This approach has two disadvantages:
- If you use the String construction method, two heap memory spaces will be opened up.
- String sharing problem. The same string may be stored multiple times, which is a waste of space.
We can use the String intern
methods to manually added to the String object string constant pool
String str1 = new String("hello") ;// 该字符串常量并没有保存在对象池之中
String str2 = "hello" ;
System.out.println(str1 == str2);
// 执行结果
false
String str1 = new String("hello").intern() ;
String str2 = "hello" ;
System.out.println(str1 == str2);
// 执行结果
true
Interview question: Please explain the difference between the instantiation of the two types of objects in the String class
- Direct assignment: Only a piece of heap memory space will be opened, and the string object can be automatically saved in the object pool for next use.
- Construction method: Two heap memory spaces will be opened up and will not be automatically saved in the object pool. You can use the intern() method to manually enter the pool.
4. Understand immutable strings
A string is an immutable object. Its content cannot be changed.
The internal implementation of the String class is also based on char[], but the String class does not provide a set method or the like to modify the internal character array.
String str = "hello" ;
str = str + " world" ;
str += "!!!" ;
System.out.println(str);
// 执行结果
hello world!!!
An operation in the form of += seems to modify the string on the surface, but it is not. The memory changes are as follows:
first store "hello" in, store the stored reference to str, then store "world" in, concatenate it into "hello world", put the reference of "hello world" to str, and then put "!! !" is stored in, and the reference after splicing is given to str.
Therefore, the result printed by str after += has changed, but it is not the String object itself that has changed, but that str refers to other objects.
Recalling references A
reference is equivalent to a pointer, and the content stored in it is an address. We have to distinguish clearly whether the current modification is whether the content of the memory corresponding to the modified address has changed, or whether the address stored in the reference has changed.
If you really need to modify the string
a) Common method : use the original string to create a new string
String str = "Hello";
str = "h" + str.substring(1);
System.out.println(str);
// 执行结果
hello
b) Special method (optional): Using operations such as "reflection" can break the encapsulation and access private members within a class.
In IDEA, ctrl + left-click to jump to the definition of the String class, you can see that a char[] is included inside, which saves the content of the string.
String str = "Hello";
// 获取 String 类中的 value 字段. 这个 value 和 String 源码中的 value 是匹配的
Field valueField=String.class.getDeclaredField("value");
// 将这个字段的访问属性设为 true
valueField.setAccessible(true);
// 把 str 中的 value 属性获取到.
char[] value = (char[]) valueField.get(str);
// 修改 value 的值
value[0] = 'h';
System.out.println(str);
// 执行结果
hello
Benefits of immutable objects:
- It is convenient to realize the string object pool. If the String is variable, then the object pool needs to consider when to deep copy the string.
- Immutable objects are thread-safe.
- Immutable objects are more convenient to cache hash code, and can be stored in HashMap more efficiently when used as keys
5. Characters, bytes and strings
5.1 Characters and strings
The string contains an array of characters, and String can be converted to char[].
No | Method name | Types of | description |
---|---|---|---|
1 | public String(char value[]) | structure | Turn everything in the array into a string |
2 | public String(char value[],int offset,int count) | structure | Part of the contents of the character array into a string |
3 | public char charAt(int index) | ordinary | Get the character at the specified index position, the index starts from 0 |
4 | public char[] toCharArray() | ordinary | Return the string into a character array |
5.2 Bytes and strings
No | Method name | Types of | description |
---|---|---|---|
1 | public String(byte bytes[]) | structure | Turn byte array into string |
2 | public String(byte bytes[],int offset,int length) | structure | Turn the contents of part of the byte array into a string |
3 | public byte[] getBytes() | ordinary | Return the string as a byte array |
4 | public byte[] getBytes(String charsetName)throw UnsupportedEncodingException | ordinary | Transcoding processing |
6. Common String Operations
6.1 String comparison
No | Method name | Types of | description |
---|---|---|---|
1 | public boolean equals(Object anObject) | ordinary | Case-sensitive comparison |
2 | public boolean equalsIgnoreCase(String anotherString) | ordinary | Case-insensitive comparison |
3 | public int compareTo(String anotherString) | ordinary | Compare the size of two strings |
The compareTo()
method in the String class is a very important method, the method returns an integer, the data will return three types of content according to the size relationship:
- Equal: return 0.
- Less than: The returned content is less than 0.
- Greater than: The returned content is greater than 0.
6.2 String search
No | Method name | Types of | description |
---|---|---|---|
1 | public boolean contains(CharSequence s) | ordinary | Determine whether a substring exists |
2 | public int indexOf(String str) | ordinary | Search the position of the specified string from the beginning, find the starting index of the returned position, and return -1 if not found |
3 | public int indexOf(String stx,int fromIndex) | ordinary | Find the position of the substring starting from the specified position |
4 | public int lastIndexOf(String str) | ordinary | Find the position of the substring from back to front |
5 | public int lastIndexOf(String str,int fromIndex) | ordinary | Search backward from the specified position |
6 | public boolean startsWith(String: prefix) | ordinary | Determine whether to start with the specified string |
7 | public boolean startsWith(String prefix, int toffset) | ordinary | Start from the specified position to determine whether it starts with the specified string |
8 | public boolean endsWith(String suffix) | ordinary | Determine whether to end with the specified string |
6.3 String replacement
No | Method name | Types of | description |
---|---|---|---|
1. | public String replaceAll(String regex, String replacement) | ordinary | Replace all specified content |
2. | public String replaceFirst(String regex,String replacement) | ordinary | Replace the first content |
6.4 String split
No | Method name | Types of | description |
---|---|---|---|
1 | public String[] split(String regex) | 普通 | 将字符串全部拆分 |
2 | public String[] split(String regex, int limit) | 普通 | 将字符串部分拆分,该数组长度就是 limit 极限 |
6.5 字符串截取
No | 方法名称 | 类型 | 描述 |
---|---|---|---|
1 | public String substring(int beginIndex) | 普通 | 从指定索引截取到结尾 |
2 | public String substring(int beginIndex, int endIndex) | 普通 | 截取部分内容 |
6.6 其他操作方法
No | 方法名称 | 类型 | 描述 |
---|---|---|---|
1 | public Stringtrim() | 普通 | 去掉字符串中的左右空格,保留中间空格 |
2 | public String toUpperCase() | 普通 | 字符串转大写 |
3 | public String toLowerCase() | 普通 | 字符串转小写 |
4 | public native String intern() | 普通 | 字符串入池操作 |
5 | public String concat(String str) | 普通 | 字符串连接,等同于“+=”,不入池 |
6 | public int length() | 普通 | 取得字符串长度 |
7 | public boolean isEmpty() | 普通 | 判断是否为空字符串,但不是null,而是长度为0 |
7. StringBuffer 和 StringBuilder
首先来回顾下String类的特点:
- 任何的字符串常量都是String对象,而且String的常量一旦声明不可改变,如果改变对象内容,改变的是其引用的指向而已。
通常来讲String的操作比较简单,但是由于String的不可更改特性,为了方便字符串的修改,提供StringBuffer
和StringBuilder
类。
StringBuffer
和 StringBuilder
大部分功能是相同的,主要介绍 StringBuffer
在String中使用"+"来进行字符串连接,但是这个操作在StringBuffer类中需要更改为append()方法:
public synchronized StringBuffer append(各种数据类型 b)
The biggest difference between String and StringBuffer is that the content of String cannot be modified, while the content of StringBuffer can be modified. Consider using StingBuffer if you frequently modify strings.
Note: The String and StringBuffer classes cannot be converted directly. If you want to convert between each other, you can use the following principles:
String becomes StringBuffer: use StringBuffer's construction method or append() method
StringBuffer becomes String: call toString() method
In addition to the append() method, StringBuffer also has some methods that the String class does not:
- String reversal:
public synchronized StringBuffer reverse()
- Delete the data in the specified range:
public synchronized StringBuffer delete(int start, int end)
- Insert data
public synchronized StringBuffer insert(int offset, 各种数据类型 b)
Interview question: Please explain the difference between String, StringBuffer and StringBuilder:
- The content of String cannot be modified, and the content of StringBuffer and StringBuilder can be modified.
- Most functions of StringBuffer and StringBuilder are similar
- StringBuffer uses synchronous processing, which is a thread-safe operation; while StringBuilder does not use synchronous processing, which is a thread-unsafe operation