Java String字符串:创建、拼接与比较,常见问题解决

I. What is String?

In Java, String is a class used to represent text data, and it is immutable (content cannot be modified once created). Due to its immutability, String is widely used in Java for storing and processing text, such as user input, file names, URLs, etc.

II. String Creation Methods

There are mainly two ways to create String objects in Java. Their memory behaviors differ, and beginners often confuse them, so careful distinction is required.

String s1 = "hello";
String s2 = "hello";
  • Principle: Java first checks the string constant pool (a special memory area for reusing identical string constants) for "hello".
  • If "hello" exists, s1 and s2 directly point to the same String object in the constant pool.
  • If not, a new "hello" is created in the constant pool, and s1/s2 point to it.
  • Feature: Identical constants are reused to save memory. For example, although s1 and s2 are separate variables, they share the same reference (s1 == s2 is true).

2. Creation with the new Keyword

String s3 = new String("hello");
String s4 = new String("hello");
  • Principle: Regardless of whether "hello" exists in the constant pool, a new String object is created in heap memory with content "hello", and the reference of the new object is independent of the constant pool.
  • Feature: Even with the same content, s3 and s4 have different references (s3 == s4 is false). The new keyword forces a new heap object, while direct assignment prioritizes constant pool reuse.

Comparison of Direct Assignment vs. new Creation

Method Reference Equality (Same Content) Memory Location Constant Pool Reuse
Direct Assignment true (constant pool reuse) Constant Pool Yes
new Creation false (new in heap) Heap Memory No (but same content constants are first added to the pool)

III. String Concatenation Operations

String concatenation is a common operation. Java provides multiple methods, and their performance and results differ; careful attention is needed.

1. Using the + Operator (Most Intuitive)

String a = "a";
String b = "b";
String c = a + b; // Result: "ab"
  • Principle: The + operator is optimized by the compiler during compilation.
  • If concatenating all constants (e.g., "a" + "b"), "ab" is directly generated in the constant pool.
  • If variables are included in the concatenation (e.g., a + b, where a/b are variables), a new String object is created in the heap.
  • Note: Frequent use of + (especially in loops) creates numerous temporary objects, leading to extremely low efficiency!

2. Using the concat() Method

String d = "a".concat("b"); // Result: "ab"
  • Principle: concat() is a String class method that returns a new string after concatenation; the original string remains unchanged (due to String immutability).
  • Example:
  String e = "hello";
  String f = e.concat("world"); // f is "helloworld", e remains "hello"

3. Using StringBuilder/StringBuffer (Efficient Concatenation)

String is immutable, so each concatenation creates a new object. In contrast, StringBuilder/StringBuffer are mutable character sequences that modify their internal arrays directly during concatenation, offering higher efficiency.
- Differences:
- StringBuilder: Non-thread-safe, more efficient in single-threaded scenarios (recommended by default).
- StringBuffer: Thread-safe (methods are synchronized), used in multi-threaded environments.

Example:

StringBuilder sb = new StringBuilder();
sb.append("a"); // Append a single character
sb.append("b"); // Append a string
String result = sb.toString(); // Convert to String (final result)

IV. String Comparison Operations

When comparing strings, == and equals() serve completely different purposes. Confusing them often leads to logical errors.

1. ==: Compare Object References (Are they the same object?)

String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");

System.out.println(s1 == s2); // true (point to the same object in the constant pool)
System.out.println(s1 == s3); // false (s3 is a new heap object with a different reference)

2. equals(): Compare String Content (Ignore References)

String s1 = "hello";
String s3 = new String("hello");

System.out.println(s1.equals(s3)); // true (content is identical)
  • Note:
  • equals() can only be used on non-null strings; otherwise, it throws NullPointerException (e.g., null.equals("a")).
  • Never use == to compare content!

3. Correctly Comparing Empty Strings

To check if a string is empty, use isEmpty() or length() == 0 instead of == "" or == null.

String s = "";
System.out.println(s.isEmpty()); // true (empty string, not null)
System.out.println(s.length() == 0); // true
System.out.println(s == ""); // true (content is the same, but not recommended)

V. Common Problems and Solutions

1. Confusing == and equals()

Wrong Scenario:

String a = new String("hello");
String b = new String("hello");
if (a == b) { // Error! == compares references; a and b are different objects
    System.out.println("a and b are the same");
} else {
    System.out.println("a and b have the same content but are different objects");
}

Solution: Use equals() to compare content:

if (a.equals(b)) { // Correct! Compares content
    System.out.println("a and b have the same content");
}

2. Frequent + Concatenation in Loops

Wrong Scenario:

String result = "";
for (int i = 0; i < 1000; i++) {
    result = result + i; // Creates new String objects in each loop, very inefficient!
}

Solution: Use StringBuilder instead of +:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append(i); // Directly modifies internal array; no extra object creation
}
String result = sb.toString(); // Final result

3. Using == "" to Check for Empty Strings

Wrong Scenario:

String s = null;
if (s == "") { // Error! null cannot be compared with == ""
    System.out.println("Empty string");
}

Solution: Check for null first, then use isEmpty():

if (s != null && s.isEmpty()) { // Recommended
    System.out.println("Empty string");
}

VI. Summary

  1. Immutability: Once created, String cannot be modified; any concatenation/modification generates a new object.
  2. Creation Methods: Direct assignment reuses the constant pool, while new forces a new heap object.
  3. Concatenation Choice: Use + or concat() for small-scale concatenation; use StringBuilder for large-scale concatenation (e.g., loops).
  4. Comparison Rules: == compares references, equals() compares content. Avoid confusion; use isEmpty() or length() == 0 for empty strings, and check null first.

Mastering these concepts avoids most common String-related errors and ensures efficient, clear Java code.

Xiaoye