AP CSA 1.15:字符串
This lesson is about reading and tracing Java code that works with text. The most important rule is simple: String methods produce results, but a variable changes only when you save or assign the result.
这一课学习如何阅读和追踪处理文本的 Java 代码。最重要的规则很简单:String 方法会产生结果,但只有保存或重新赋值这个结果,变量才会改变。
A String method may produce a new String, but it does not rewrite the original String. String 方法可以产生一个新字符串,但不会直接改写原来的字符串。
Core Concepts:
核心知识点
1. The First AP Exam Idea
第一个 AP 核心考法
Consider this AP-style output question:
请看这道 AP 风格的输出题:
String s = "Hello";
s.substring(1);
System.out.println(s);
What is printed?
输出是什么?
Hello
substring(1) produces the String "ello", but the program does not save that result. The variable s still refers to "Hello".
substring(1) 会产生字符串 "ello",但程序没有保存这个结果。因此,变量 s 仍然指向 "Hello"。
Now compare:
String s = "Hello";
s = s.substring(1);
System.out.println(s);
Output:
ello
This time, the result is assigned back to s.
这一次,程序把结果重新赋值给了 s。
The official vocabulary is immutable. In plain English, a String does not change in place. Java creates a new result, and the variable can be reassigned to that result.
这个特点的正式术语是 不可变性(immutable)。简单来说,字符串不会被“原地修改”。Java 会产生一个新结果,而变量可以重新指向这个结果。
For AP questions, use this rule:
做 AP 题时,记住:
Method result not saved → variable stays the same
Method result assigned → variable gets the new String
方法结果没有保存 → 变量保持不变
方法结果被重新赋值 → 变量得到新字符串
2. String Basics
String 基础
A String stores text as a sequence of characters.
String 用来保存由字符组成的文本。
String name = "Evie";
String message = "Hello!";
String starts with a capital letter because it is a class type, not a primitive type such as int, double, or boolean.
String 以大写字母开头,因为它是类类型,不是 int、double 或 boolean 这样的基本类型。
The common way to create a String is with a string literal:
最常见的创建方式是使用字符串字面量:
String greeting = "Hello";
This is also valid:
下面的写法也合法:
String greeting = new String("Hello");
For AP CSA questions, the first form is more common.
在 AP CSA 题目中,第一种写法更常见。
3. String Concatenation
字符串拼接
The + operator joins values together when a String is involved. This is called concatenation.
当表达式中出现 String 时,+ 可以连接内容。这个操作叫作字符串拼接(concatenation)。
String firstName = "Evie";
String message = "Hello, " + firstName + "!";
System.out.println(message);
Output:
Hello, Evie!
Java does not add spaces automatically.
Java 不会自动添加空格。
System.out.println("Hello" + "Evie");
Output:
HelloEvie
Add the space yourself:
要自己加入空格:
System.out.println("Hello" + " " + "Evie");
Numbers and concatenation
数字与字符串拼接
This pattern often appears in output-tracing questions:
这种写法经常出现在输出题中:
System.out.println("12" + 4 + 3);
Output:
1243
Java evaluates from left to right:
Java 从左向右计算:
"12" + 4 → "124"
"124" + 3 → "1243"
To calculate 4 + 3 first, use parentheses:
如果希望先计算 4 + 3,要使用括号:
System.out.println("12" + (4 + 3));
Output:
127
Compare these common AP-style expressions:
比较下面这些常见的 AP 风格表达式:
| Expression | Result |
|---|---|
"12" + 4 + 3 |
"1243" |
"12" + (4 + 3) |
"127" |
4 + 3 + "12" |
"712" |
With +=, Java creates a new String and assigns it back to the variable.
使用 += 时,Java 会产生一个新字符串,再把它赋回变量。
String word = "cat";
word += "s";
System.out.println(word);
Output:
cats
4. Index and Length
索引与长度
Each character in a String has an index. Indexes start at 0.
字符串中的每个字符都有一个索引,索引从 0 开始。
For this String:
对于这个字符串:
String word = "baby";
| Character | b |
a |
b |
y |
|---|---|---|---|---|
| Index | 0 | 1 | 2 | 3 |
The length is 4.
长度是 4。
System.out.println(word.length());
Output:
4
The last index is not the length. It is one less than the length.
最后一个索引不等于长度,而是长度减 1。
first index = 0
last index = length() - 1
Spaces and punctuation also count as characters.
空格和标点符号也算字符。
String text = "Hi!";
System.out.println(text.length());
Output:
3
5. The substring Methods
substring 方法
substring(from, to)
str.substring(from, to)
The starting index is included. The ending index is not included.
开始位置包含,结束位置不包含。
A useful way to remember it is:
可以这样记:
[from, to)
Example:
String word = "baby";
String part = word.substring(0, 3);
System.out.println(part);
Output:
bab
It uses indexes 0, 1, and 2. It stops before index 3.
它使用索引 0、1、2,并在索引 3 之前停止。
substring(from)
String word = "baby";
System.out.println(word.substring(2));
Output:
by
This returns everything from index 2 through the end.
它返回从索引 2 一直到结尾的内容。
Getting one character
得到一个字符
To get the character at index i as a one-character String:
要把索引 i 位置的字符提取为一个长度为 1 的字符串:
str.substring(i, i + 1)
Example:
String word = "baby";
System.out.println(word.substring(1, 2));
Output:
a
Empty substrings
空字符串
This is valid:
下面的代码合法:
String word = "baby";
System.out.println(word.substring(2, 2));
It returns an empty String because the starting and ending indexes are the same.
它返回空字符串,因为开始和结束索引相同。
This is also valid:
下面的写法也合法:
word.substring(word.length())
It returns an empty String. It does not return the last character.
它返回空字符串,不会返回最后一个字符。
To get the last character:
要得到最后一个字符:
word.substring(word.length() - 1)
6. Valid Indexes and Runtime Errors
合法索引与运行时错误
For:
str.substring(from, to)
the indexes must satisfy:
索引必须满足:
0 <= from <= to <= str.length()
These calls are invalid:
下面这些调用不合法:
str.substring(-1, 3);
str.substring(2, 10);
str.substring(4, 2);
They cause an IndexOutOfBoundsException.
它们会导致 IndexOutOfBoundsException。
This is a runtime error: the program can compile, but it stops when the invalid line runs.
这是运行时错误:程序可能可以编译,但执行到非法索引时会停止。
For AP questions, you usually only need to recognize that the program causes an exception. You do not need to reproduce the full error message.
在 AP 题中,通常只需要判断程序会产生异常,不需要写出完整报错信息。
7. The indexOf Method
indexOf 方法
indexOf searches for one String inside another String.
indexOf 用来查找一个字符串在另一个字符串中的位置。
String text = "abccba";
int position = text.indexOf("b");
System.out.println(position);
Output:
1
It returns the index of the first match.
它返回第一次匹配的位置。
String text = "This is a test";
System.out.println(text.indexOf("is"));
Output:
2
It finds the "is" inside "This" first.
它首先找到 "This" 中的 "is"。
If the target is not found, indexOf returns -1.
如果没有找到,indexOf 返回 -1。
System.out.println("Hello".indexOf("z"));
Output:
-1
The search is case-sensitive.
查找区分大小写。
"Hello".indexOf("H") // 0
"Hello".indexOf("h") // -1
8. Comparing Strings
比较字符串
equals
Use equals when you want to know whether two Strings contain the same characters in the same order.
如果要判断两个字符串的字符内容是否完全相同,要使用 equals。
String a = new String("cat");
String b = new String("cat");
System.out.println(a.equals(b));
Output:
true
Do not use == to compare String contents.
不要使用 == 比较字符串内容。
System.out.println(a == b);
Output:
false
a and b contain the same text, but they refer to two different objects.
a 和 b 的文字内容相同,但它们指向两个不同的对象。
For AP questions:
做 AP 题时:
same text → use equals()
same reference → ==
比较文字内容 → 使用 equals()
比较是否指向同一对象 → 使用 ==
equals is case-sensitive:
equals 区分大小写:
"Hello".equals("hello")
Result:
false
compareTo
compareTo tells you whether one String comes before, matches, or comes after another String.
compareTo 用来判断一个字符串排在另一个字符串之前、相同还是之后。
s1.compareTo(s2)
| Result | Meaning |
|---|---|
< 0 |
s1 comes before s2 |
0 |
the Strings contain the same characters |
> 0 |
s1 comes after s2 |
Example:
System.out.println("Bye".compareTo("Hi"));
The result is negative because "Bye" comes before "Hi".
结果是负数,因为 "Bye" 排在 "Hi" 前面。
For AP CSA, the exact number usually does not matter. Focus on whether the result is negative, zero, or positive.
在 AP CSA 中,通常不需要知道具体数字,只需要判断结果是负数、0 还是正数。
How does compareTo() decide the order?
compareTo() 如何判断先后顺序?
Java compares the Strings one character at a time from left to right. As soon as it finds two different characters, it uses those characters to decide the result.
Java 会从左到右逐个比较字符。一旦找到第一组不同的字符,就用这两个字符判断先后顺序。
For the characters commonly tested in AP CSA, remember this order:
在 AP CSA 常见题目中,可以记住下面的顺序:
numbers < uppercase letters < lowercase letters
数字 < 大写字母 < 小写字母
More specifically:
具体来说:
0 < 1 < 2 < ... < 9
A < B < C < ... < Z
a < b < c < ... < z
Putting the three groups together:
把三组字符放在一起:
0–9 → A–Z → a–z
Therefore:
因此:
"8".compareTo("A") // negative
"A".compareTo("a") // negative
"a".compareTo("9") // positive
A useful memory example is:
一个方便记忆的例子是:
"9" comes before "A"
"A" comes before "a"
This means Java’s ordering is not always the same as ordinary dictionary ordering.
这意味着 Java 的排序方式不一定和我们平时使用的字典顺序完全相同。
For example:
例如:
"Zoo".compareTo("apple")
The result is negative because uppercase "Z" comes before lowercase "a".
结果是负数,因为大写 "Z" 排在小写 "a" 前面。
Remember that Java stops at the first different character:
记住,Java 会在第一个不同的字符处决定结果:
"Cat".compareTo("Car")
The first two characters, "C" and "a", are the same. Java then compares "t" with "r". Because "t" comes after "r", the result is positive.
前两个字符 "C" 和 "a" 相同,所以 Java 接着比较 "t" 和 "r"。因为 "t" 排在 "r" 后面,所以结果是正数。
For AP CSA, focus on the sign:
在 AP CSA 中,重点判断正负:
negative → the first String comes before the second
zero → the two Strings are equal
positive → the first String comes after the second
9. Common Beginner Mistakes
常见初学者错误
| Mistake | Wrong Code or Idea | Why It Is Wrong | Correct Form | 中文解释 |
|---|---|---|---|---|
| Ignoring the returned String | s.substring(1); |
The new result is not saved | s = s.substring(1); |
要保存方法返回的新字符串 |
| Including the ending index | Thinking substring(0, 3) includes index 3 |
The ending index is excluded | It uses indexes 0 through 2 |
结束索引不包含 |
Using length() as the last index |
s.substring(s.length()) |
This returns an empty String | s.substring(s.length() - 1) |
最后索引是长度减 1 |
Comparing contents with == |
s1 == s2 |
It compares references | s1.equals(s2) |
字符串内容用 equals 比较 |
| Forgetting case sensitivity | Thinking "Hi".equals("hi") is true |
Uppercase and lowercase differ | The result is false |
大小写不同 |
Calling a method on null |
String s = null; s.length(); |
No String object exists | Assign a String first | 会产生空指针异常 |
10. Debugging Example
调试例子
Buggy code:
public class StringMistakes
{
public static void main(String[] args)
{
String str = "Hello!";
System.out.println(str.substring(1, 1));
System.out.println(str.substring(8));
str.substring(1);
System.out.println(str);
}
}
There are three problems:
这里有三个问题:
-
substring(1, 1)returns an empty String, not the first character. -
Index
8is outside the String, so the program stops with an exception. -
substring(1)returns a new String, but the result is not saved. -
substring(1, 1)返回空字符串,不是第一个字符。 -
索引
8超出范围,所以程序会因异常停止。 -
substring(1)返回新字符串,但结果没有被保存。
Fixed code:
public class StringMistakes
{
public static void main(String[] args)
{
String str = "Hello!";
System.out.println(str.substring(0, 1));
System.out.println(str.substring(str.length() - 1));
str = str.substring(1);
System.out.println(str);
}
}
Output:
H
!
ello!
| Bug | Error Type | Fix |
|---|---|---|
| Wrong substring boundaries | Logic error | Use the correct indexes |
| Index outside the String | Runtime error | Stay within the valid range |
| Returned value ignored | Logic error | Assign or use the result |
11. Mini Practice
小练习
Practice 1: String Methods and Reassignment
练习 1:String 方法与重新赋值
What is printed?
String s = "Hello";
s.substring(1);
System.out.println(s);
A. Hello
B. ello
C. H
D. The code does not compile
Answer:
A. Hello
substring(1) returns "ello", but the result is not assigned or used.
substring(1) 返回 "ello",但结果没有被保存或使用。
Practice 2: Concatenation
练习 2:字符串拼接
What is printed?
System.out.println("Score: " + 4 + 3);
System.out.println("Score: " + (4 + 3));
Answer:
Score: 43
Score: 7
The first expression concatenates from left to right. The second calculates inside the parentheses first.
第一个表达式从左向右拼接;第二个表达式先计算括号中的加法。
Practice 3: substring and indexOf
练习 3:substring 与 indexOf
What is stored in result?
String text = "hi there";
int pos = text.indexOf("e");
String result = text.substring(0, pos);
Answer:
hi th
The first "e" is at index 5, and substring(0, 5) stops before index 5.
第一个 "e" 在索引 5,而 substring(0, 5) 在索引 5 之前停止。
Practice 4: Comparing Strings
练习 4:比较字符串
What is printed?
String a = new String("Java");
String b = new String("Java");
System.out.println(a.equals(b));
System.out.println(a == b);
Answer:
true
false
equals compares the text. == checks whether the references point to the same object.
equals 比较文字内容;== 检查两个引用是否指向同一个对象。
Practice 5: Fix the Code
练习 5:修复代码
The goal is to print the last character of word.
String word = "Java";
System.out.println(word.substring(word.length()));
Fixed code:
String word = "Java";
System.out.println(word.substring(word.length() - 1));
Output:
a
substring(word.length()) is valid, but it returns an empty String. The last character begins at length() - 1.
substring(word.length()) 是合法的,但它返回空字符串。最后一个字符从 length() - 1 开始。
Quick Checklist
快速检查清单
Before answering a String question, check:
做字符串题前,检查:
- Did the String method return a value?
- Was that returned value saved, printed, or used?
- Did the variable actually get reassigned?
- Is the expression doing arithmetic or String concatenation?
- Is the expression evaluated from left to right?
- Are spaces included explicitly?
- Does indexing start at
0? - Is the last character at
length() - 1? - Does
substring(from, to)includefrombut excludeto? - Could the substring be empty?
- Are the indexes within the valid range?
- Does
indexOfreturn the first match or-1? - Are String contents compared with
equals, not==? - For
compareTo, is the result negative, zero, or positive? - Are uppercase and lowercase treated as different characters?
- Could the reference be
null?