一、回顾与本篇目标
前面八篇,你从零开始学会了 Java 的基本语法、条件判断、循环、数组,以及面向对象的三大核心特性——封装、继承、多态。现在你已经能用面向对象的方式写出结构清晰的程序了。
在写程序的过程中,有两个东西你几乎每时每刻都会用到:字符串和列表。字符串用来处理文本——用户输入的名字、邮箱、文章内容都是字符串。列表用来存储一组数据——学生的成绩、商品的信息、待办事项的清单。Java 提供了两个非常强大的类来分别处理这两种需求:String 和 ArrayList。
String 你其实已经在用了——从第一篇开始,"Hello World" 就是一个字符串。但 String 远不止是“用双引号包裹的一段文字”,它有几十个非常有用的方法,比如截取子串、替换内容、查找字符位置、大小写转换。ArrayList 则是一种动态数组——和普通数组不同,它的长度可以自动增长和缩小,不用提前确定大小。
本篇的目标:
- 理解 String 是引用类型,不是基本类型
- 掌握 String 最常用的十几个方法
- 学会用 StringBuilder 高效拼接字符串
- 理解 ArrayList 和普通数组的区别
- 掌握 ArrayList 的增删改查和遍历
二、String——字符串
2.1 String 是引用类型
在第二篇中我们学了八种基本数据类型(int、double、char、boolean 等)。String 不在其中——String 是一个类,属于引用类型。但因为它太常用了,Java 给了它特殊的待遇:可以像基本类型一样直接用双引号创建。
// 两种创建字符串的方式
// 方式一:直接用双引号(最常用,和基本类型一样方便)
String name = "张三";
// 方式二:用 new 关键字(和其他引用类型一样)
String name2 = new String("张三");
// 两种方式创建的都是 String 对象,但方式一更简洁,是推荐写法
String 的内容不可变:一旦创建了一个 String 对象,它的内容就不能被修改。所有看起来“修改”了字符串的操作(比如转大写、替换),实际上都是创建了一个新的 String 对象,原来的字符串没有变。
String text = "hello";
String upperText = text.toUpperCase(); // 创建了一个新字符串 "HELLO"
System.out.println(text); // hello —— 原来的没变
System.out.println(upperText); // HELLO —— 新创建的字符串
2.2 获取字符串长度
用 length() 方法获取字符串的字符个数:
String text = "Hello World";
System.out.println(text.length()); // 11(空格也算一个字符)
String chinese = "你好世界";
System.out.println(chinese.length()); // 4(一个中文也是一个字符)
注意:length() 是一个方法,后面有括号。这和数组的 length 属性不同(数组的 length 没有括号)。这是初学者经常搞混的地方。
int[] arr = {1, 2, 3};
System.out.println(arr.length); // 属性,没有括号 —— 3
String str = "abc";
System.out.println(str.length()); // 方法,有括号 —— 3
2.3 获取指定位置的字符
用 charAt(索引) 获取字符串中某个位置的字符。索引从 0 开始:
String text = "Hello";
System.out.println(text.charAt(0)); // H —— 第一个字符
System.out.println(text.charAt(1)); // e —— 第二个字符
System.out.println(text.charAt(4)); // o —— 最后一个字符
// 遍历字符串的每个字符
for (int i = 0; i < text.length(); i++) {
System.out.print(text.charAt(i) + " "); // H e l l o
}
2.4 截取子串
用 substring(开始索引, 结束索引) 截取一部分:
String text = "Hello World";
// 从索引 0 截取到索引 5(不包括 5)
System.out.println(text.substring(0, 5)); // Hello
// 从索引 6 截取到末尾
System.out.println(text.substring(6)); // World
// 从索引 3 截取到索引 7
System.out.println(text.substring(3, 8)); // lo Wo
规则:substring(开始, 结束)——包含开始,不包含结束。如果只写一个参数,就从那个位置截取到末尾。
2.5 查找子串位置
用 indexOf() 查找某个子串第一次出现的位置:
String text = "Hello World";
System.out.println(text.indexOf("World")); // 6 —— "World" 从索引 6 开始
System.out.println(text.indexOf("o")); // 4 —— 第一个 "o" 在索引 4
System.out.println(text.indexOf("xyz")); // -1 —— 没找到返回 -1
// 从指定位置开始查找
System.out.println(text.indexOf("o", 5)); // 7 —— 从索引 5 开始找,找到第二个 "o"
// lastIndexOf:查找最后一次出现的位置
System.out.println(text.lastIndexOf("o")); // 7 —— 最后一个 "o" 在索引 7
2.6 替换内容
用 replace() 替换字符串中的内容:
String text = "Hello World";
// 替换所有匹配的字符或字符串
System.out.println(text.replace("o", "0")); // Hell0 W0rld
System.out.println(text.replace("World", "Java")); // Hello Java
2.7 去除首尾空白
用 trim() 去除字符串开头和结尾的空白字符(空格、Tab、换行等):
String input = " 张三 ";
System.out.println("[" + input + "]"); // [ 张三 ]
System.out.println("[" + input.trim() + "]"); // [张三]
这在处理用户输入时非常有用——用户可能在名字前后多打了空格,用 trim() 可以清理掉。
2.8 大小写转换
String text = "Hello World";
System.out.println(text.toUpperCase()); // HELLO WORLD —— 全部大写
System.out.println(text.toLowerCase()); // hello world —— 全部小写
2.9 判断是否以某内容开头或结尾
String filename = "report.pdf";
System.out.println(filename.startsWith("report")); // true
System.out.println(filename.endsWith(".pdf")); // true
System.out.println(filename.endsWith(".doc")); // false
2.10 字符串比较——用 equals 而不是 ==
这是一个非常重要的知识点。在 Java 中比较两个字符串的内容是否相同,必须使用 equals() 方法,不能用 ==。
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
// == 比较的是内存地址(两个变量是否指向同一个对象)
System.out.println(s1 == s2); // true(这种情况特殊,因为字符串常量池)
System.out.println(s1 == s3); // false(s3 是 new 出来的,地址不同)
// equals 比较的是内容
System.out.println(s1.equals(s2)); // true(内容相同)
System.out.println(s1.equals(s3)); // true(内容相同)
// equalsIgnoreCase:忽略大小写比较
System.out.println("Hello".equalsIgnoreCase("hello")); // true
一句话规则:比较字符串内容永远用 equals(),不要用 ==。
2.11 判断是否为空
String str1 = "";
String str2 = " ";
String str3 = null;
// isEmpty():判断长度是否为 0
System.out.println(str1.isEmpty()); // true
// isBlank()(Java 11+):判断是否为空或只包含空白字符
// System.out.println(str2.isBlank()); // true
// 判断是否为 null
System.out.println(str3 == null); // true
三、StringBuilder——高效拼接字符串
如果你需要在循环中频繁地拼接字符串,直接用 + 号效率很低——因为 String 是不可变的,每次拼接都会创建一个新的 String 对象。Java 提供了 StringBuilder 来解决这个问题。
// 低效的方式:用 + 号在循环中拼接(每次创建新对象)
String result1 = "";
for (int i = 1; i <= 5; i++) {
result1 = result1 + i + " "; // 每次都创建新字符串
}
System.out.println(result1); // 1 2 3 4 5
// 高效的方式:用 StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 5; i++) {
sb.append(i).append(" "); // 往同一个对象里追加
}
String result2 = sb.toString();
System.out.println(result2); // 1 2 3 4 5
StringBuilder 常用方法:
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 追加:Hello World
sb.insert(5, " Java"); // 在索引 5 插入:Hello Java World
sb.replace(6, 10, "C++"); // 替换索引 6-10:Hello C++ World
sb.delete(5, 9); // 删除索引 5-9:Hello World
sb.reverse(); // 反转:dlroW olleH
System.out.println(sb.toString()); // 最终转成 String
什么时候用 StringBuilder:在循环中拼接字符串时使用。平时简单的拼接(如 "你好" + name),直接使用 + 号就够了——编译器会自动优化。
四、ArrayList——动态数组
4.1 为什么需要 ArrayList
在第六篇中我们学了普通数组——int[] arr = new int[5];。普通数组有一个最大的缺点:大小在创建时就定死了,之后不能改变。如果你一开始不知道要存多少个数据(比如用户输入的班级人数是运行时才确定的),就无法确定数组的大小。
ArrayList 就是一种能自动伸缩的数组——你不必提前确定大小,添加元素时它自动扩容,删除元素时它自动缩容。
// 普通数组:大小固定
int[] arr = new int[5]; // 只能存 5 个元素,不能超过
// ArrayList:大小动态变化
ArrayList list = new ArrayList<>(); // 不指定大小,可以随意添加
4.2 创建 ArrayList
ArrayList 在 java.util 包中,使用前需要导入。语法中有一对尖括号 <>,里面写要存储的数据类型:
import java.util.ArrayList; // 导入 ArrayList
public class ArrayListDemo {
public static void main(String[] args) {
// 创建一个存储字符串的 ArrayList
ArrayList names = new ArrayList<>();
// 创建一个存储整数的 ArrayList
// 注意:尖括号里不能写基本类型,要写包装类 Integer
ArrayList scores = new ArrayList<>();
// 创建一个存储小数的 ArrayList
ArrayList prices = new ArrayList<>();
}
}
为什么是 Integer 而不是 int:尖括号 <> 里只能写引用类型,不能写基本类型。Java 为每种基本类型提供了对应的包装类:
| 基本类型 | 包装类 |
|---|---|
int |
Integer |
double |
Double |
char |
Character |
boolean |
Boolean |
Java 会在基本类型和包装类之间自动转换(自动装箱和拆箱),所以你用起来和基本类型几乎没有区别:
ArrayList list = new ArrayList<>();
list.add(10); // 自动把 int 10 转换成 Integer
int num = list.get(0); // 自动把 Integer 转换回 int
4.3 ArrayList 的增删改查
import java.util.ArrayList;
public class ArrayListOperations {
public static void main(String[] args) {
ArrayList fruits = new ArrayList<>();
// 1. 添加元素
fruits.add("苹果"); // 在末尾添加
fruits.add("香蕉");
fruits.add("橘子");
fruits.add(1, "草莓"); // 在索引 1 的位置插入
System.out.println(fruits); // [苹果, 草莓, 香蕉, 橘子]
// 2. 获取元素
String first = fruits.get(0); // 获取索引 0 的元素
String second = fruits.get(1); // 获取索引 1 的元素
System.out.println("第一个:" + first); // 苹果
System.out.println("第二个:" + second); // 草莓
// 3. 获取大小
System.out.println("元素个数:" + fruits.size()); // 4
// 4. 修改元素
fruits.set(1, "西瓜"); // 把索引 1 的元素改成"西瓜"
System.out.println(fruits); // [苹果, 西瓜, 香蕉, 橘子]
// 5. 删除元素
fruits.remove(2); // 删除索引 2 的元素(香蕉)
fruits.remove("橘子"); // 删除值为"橘子"的元素
System.out.println(fruits); // [苹果, 西瓜]
// 6. 判断是否包含
System.out.println(fruits.contains("苹果")); // true
System.out.println(fruits.contains("香蕉")); // false
// 7. 判断是否为空
System.out.println(fruits.isEmpty()); // false
// 8. 清空所有元素
fruits.clear();
System.out.println(fruits.isEmpty()); // true
}
}
4.4 遍历 ArrayList
import java.util.ArrayList;
public class ArrayListTraversal {
public static void main(String[] args) {
ArrayList fruits = new ArrayList<>();
fruits.add("苹果");
fruits.add("香蕉");
fruits.add("橘子");
fruits.add("葡萄");
// 方式一:普通 for 循环(按索引访问)
System.out.println("===== 普通 for 循环 =====");
for (int i = 0; i < fruits.size(); i++) {
System.out.println("第 " + (i + 1) + " 个:" + fruits.get(i));
}
// 方式二:增强 for 循环(最简洁)
System.out.println("===== 增强 for 循环 =====");
for (String fruit : fruits) {
System.out.println(fruit);
}
}
}
和普通数组一样:
- 需要索引时用普通 for 循环。
- 只需要值时用增强 for 循环。
4.5 ArrayList vs 普通数组
| 特性 | 普通数组 | ArrayList |
|---|---|---|
| 创建方式 | int[] arr = new int[5]; |
ArrayList list = new ArrayList<>(); |
| 大小 | 固定,不能改变 | 动态,自动伸缩 |
| 获取大小 | arr.length(属性) |
list.size()(方法) |
| 访问元素 | arr[0] |
list.get(0) |
| 修改元素 | arr[0] = 10; |
list.set(0, 10); |
| 添加元素 | 不能(长度固定) | list.add(10); |
| 删除元素 | 不能 | list.remove(0); |
| 存储基本类型 | ✅ 可以 | ❌ 必须用包装类(如 Integer) |
五、综合演示:学生名单管理
下面这个示例综合运用了 String 的方法和 ArrayList 的操作:
import java.util.ArrayList;
public class StudentManager {
public static void main(String[] args) {
ArrayList students = new ArrayList<>();
// 添加学生
students.add("张三");
students.add("李四");
students.add("王五");
students.add("赵六");
students.add("孙七");
System.out.println("===== 学生名单 =====");
printList(students);
// 查找名字中包含"三"的学生
System.out.println("\n===== 名字中含"三"的学生 =====");
for (String name : students) {
if (name.contains("三")) {
System.out.println(name);
}
}
// 把所有名字转成大写输出
System.out.println("\n===== 大写名单 =====");
for (String name : students) {
System.out.print(name.toUpperCase() + " ");
}
System.out.println();
// 删除名字长度大于 2 的学生(中文名超过两个字)
// 注意:从后往前删,避免索引错乱
for (int i = students.size() - 1; i >= 0; i--) {
if (students.get(i).length() > 2) {
System.out.println("\n删除了:" + students.remove(i));
}
}
System.out.println("\n===== 删除后名单 =====");
printList(students);
}
// 辅助方法:打印列表
public static void printList(ArrayList list) {
if (list.isEmpty()) {
System.out.println("列表为空");
return;
}
for (int i = 0; i < list.size(); i++) {
System.out.println((i + 1) + ". " + list.get(i));
}
}
}
输出:
===== 学生名单 =====
1. 张三
2. 李四
3. 王五
4. 赵六
5. 孙七
===== 名字中含"三"的学生 =====
张三
===== 大写名单 =====
张三 李四 王五 赵六 孙七
删除了:孙七
===== 删除后名单 =====
1. 张三
2. 李四
关键点:删除元素时从后往前遍历。因为删除一个元素后,后面元素的索引会自动前移。如果从前往后删,可能会跳过某些元素。
六、本篇动手练习
练习 1:字符串处理
新建 Practice9_1.java。让用户输入一个邮箱地址,判断是否包含 @、是否以 .com 结尾、提取用户名部分(@ 之前的部分)。由于还没学键盘输入,可以把邮箱地址直接写在代码里。
练习 2:StringBuilder 练习
新建 Practice9_2.java。用 StringBuilder 把 1 到 10 的数字拼接成字符串 "1, 2, 3, ..., 10"。要求数字之间用逗号加空格分隔。
练习 3:ArrayList 增删改查
新建 Practice9_3.java。创建一个存储分数的 ArrayList。添加 5 个分数,然后:输出所有分数、计算平均分、找到最高分、删除所有不及格(小于 60)的分数、再次输出。
练习 4:购物清单
新建 Practice9_4.java。创建 Product 类(属性:名称、价格),然后创建一个 ArrayList 模拟购物清单。实现:添加商品、计算总价、找出最贵的商品、删除所有价格超过 100 元的商品。
七、本篇小结
这一篇你学会了 Java 中两个最常用的工具:
- String:引用类型,内容不可变。常用方法:
length()(长度)、charAt()(取字符)、substring()(截取)、indexOf()(查找)、replace()(替换)、trim()(去空白)、toUpperCase()/toLowerCase()(大小写转换)、equals()(比较内容,不能用==)。 - StringBuilder:可变字符串,用于高效拼接。主要方法:
append()(追加)、insert()(插入)、delete()(删除)、toString()(转成 String)。 - ArrayList:动态数组,大小自动伸缩。创建时用
new ArrayList<>(),尖括号里写包装类(如Integer而不是int)。常用方法:add()(添加)、get()(获取)、set()(修改)、remove()(删除)、size()(大小)、contains()(判断存在)、clear()(清空)。
String 和 ArrayList 是日常编程中最频繁使用的两个类。下一篇,我们将学习 Java 中的异常处理机制——用 try/catch 优雅地处理错误,以及如何读写文件,让数据能持久化保存。
下一篇预告
下一篇——《异常处理与文件读写》:什么是异常、try/catch/finally 语法、常见异常类型、文件读取(FileReader/BufferedReader)、文件写入(FileWriter/BufferedWriter)。让程序能处理意外情况,并能把数据保存到硬盘上。
Java 零基础入门,每周更新。












暂无评论内容