Java 入门与核心基础
本文是一份 Java 入门与核心基础教程,覆盖 JDK 安装、开发环境搭建、基础语法、变量、运算符、流程控制、数组、方法、面向对象、String 基础与 StringBuilder 入门等内容。文章通过循序渐进的代码示例,帮助读者建立 Java 编程的完整基础认知。
第一章 开发环境搭建
1.1 初识 Java
Java 的故事
Java 是 1995 年诞生的高级编程语言,最大特点是 “一次编写,到处运行” 。你在一台电脑上写好的 Java 程序,放到另一台完全不同操作系统的电脑上也能直接运行,靠的就是 JVM(Java 虚拟机)。现在 Java 广泛应用于企业级应用、手机 App 开发、大数据等领域。
安装 JDK
JDK 是开发 Java 程序的工具箱。学习与企业开发建议安装 JDK 17 LTS(长期支持版本)。
下载渠道(任选其一):
- Eclipse Temurin(社区常用,免费)
- Amazon Corretto
- Oracle JDK(需注意许可协议)
Windows 安装示例:下载 jdk-17_windows-x64.msi 或 .exe,双击安装并记住路径,例如 C:\Program Files\Java\jdk-17。
常用 DOS 命令(Windows 必会)
我们先通过小黑窗(命令提示符)感受一下如何与电脑“对话”。 按下 Win + R,输入 cmd 回车,出现黑色窗口后尝试:
D: # 切换到 D 盘
cd java_demo # 进入 java_demo 文件夹
dir # 查看当前文件夹里的内容
cd .. # 回到上一级
第一个 Java 程序:HelloWorld
Step 1:写代码 在 D 盘新建文件夹 java_demo,里面新建一个 HelloWorld.java 文件(注意文件扩展名是 .java)。用记事本打开,输入以下代码:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, 小白你好!");
}
}
代码解释(小白第一眼不用完全理解,先照着写):
public class HelloWorld:定义了一个公开的类,类名HelloWorld必须和文件名一模一样。public static void main(String[] args):这是程序的“入口”,Java 程序会从这里一句一句往下执行。System.out.println(...):在屏幕上打印括号里的内容,运行后就能看到 “Hello, 小白你好!”。
Step 2:编译 在地址栏输入 cmd 打开命令行,执行:
javac HelloWorld.java
如果没有出现任何错误提示,文件夹里就会多出一个 HelloWorld.class 文件,这就是编译好的字节码。
Step 3:运行 继续输入:
java HelloWorld
屏幕上显示 Hello, 小白你好!,恭喜你,第一个程序成功运行!
常见错误处理
- 提示
错误: 找不到文件:检查文件名后缀是否为.java以及是否打开了“隐藏已知文件类型的扩展名”。 - 提示
错误: 需要 ';':Java 每条语句结尾必须写分号;,忘记会报错。 - 提示
HelloWorld.java:3: 错误: 找不到符号:多是因为大小写写错,比如把System写成了system。
Java 程序执行原理(简要)
.java 源文件 --[编译(javac)]--> .class 字节码文件 --[运行在 JVM]--> 屏幕输出。 JVM 在不同系统上都是一个“中间翻译”,让同一份字节码到处都能跑。
1.2 配置环境变量与 IntelliJ IDEA
Path 环境变量
为什么我们能在任何文件夹下运行 javac?因为系统知道它在哪里。需要把 JDK 的 bin 目录告诉系统:
- 右键“此电脑” → 属性 → 高级系统设置 → 环境变量。
- 系统变量里新建
JAVA_HOME,变量值填 JDK 安装路径,比如C:\Program Files\Java\jdk-17。 - 在系统变量里找到
Path,编辑,新增一行%JAVA_HOME%\bin。 - 打开一个新的命令行,输入
javac -version,出现版本号就说明配置成功。
IntelliJ IDEA 工具
IDEA 是写 Java 的神器,免费社区版就够用。下载安装后,我们创建第一个工程:
- 新建项目,选 Java,设置好 JDK 版本。
- 在
src文件夹右键 → New → Java Class,取名HelloIDEA。 - 在类里写
main方法并运行:
public class HelloIDEA {
public static void main(String[] args) {
System.out.println("IDEA 真好用!");
}
}
点击行号左边的绿色三角,就能看到结果。 IDEA 小技巧:输入 psvm 回车立刻生成 main 方法;sout 回车立刻生成 System.out.println()。
第二章 基础语法(第一行程序逻辑)
2.1 注释、关键字和字面量
注释:给人看的内容,程序不会执行。
// 这是单行注释
/*
这是多行注释
可以写很多行
*/
/**
* 文档注释,通常用在类和方法上
*/
public class Demo {
public static void main(String[] args) {
System.out.println("注释演示"); // 行尾注释
}
}
关键字:Java 自己预留的特殊单词,比如 public, class, static, void,我们给变量起名不能和它们重名。
字面量:直接写出来的常量。
System.out.println(10); // 整数
System.out.println(3.14); // 小数
System.out.println('A'); // 字符,单引号
System.out.println("Hello"); // 字符串,双引号
System.out.println(true); // 布尔值
2.2 变量与数据类型
变量:存放数据的“小盒子”,里面的值可以变化。 定义格式:数据类型 变量名 = 初始值;
public class VarDemo {
public static void main(String[] args) {
int age = 20; // 整数
double score = 88.5; // 小数
char gender = '男'; // 单个字符
String name = "张三"; // 字符串(注意 String 大写)
boolean flag = true; // 布尔,只有 true 或 false
System.out.println(age);
System.out.println(name);
}
}
使用变量注意事项:
- 不能重名,同一个大括号里只能定义一次同名变量。
- 变量必须先赋值再使用,否则编译报错。
- 起名要见名知意,用驼峰命名法:
studentName,maxScore。
基本数据类型(8 种):
- 整数:
byte(很小),short(较小),int(默认常用),long(大,加L) - 小数:
float(加F),double(默认) - 字符:
char - 布尔:
boolean
代码演示:
long bigNum = 10000000000L; // long 类型加 L
float price = 9.9F; // float 类型加 F
2.3 运算符
算术运算:+ - * / %
int a = 10, b = 3;
System.out.println(a + b); // 13
System.out.println(a - b); // 7
System.out.println(a * b); // 30
System.out.println(a / b); // 3 (整数除法,舍弃小数)
System.out.println(a % b); // 1 (取余)
字符串拼接:+ 一边是字符串,就会拼接。
String name = "小明";
int age = 18;
System.out.println(name + "今年" + age + "岁"); // 小明今年18岁
自增自减:++ 和 --
int x = 5;
x++; // x 变为 6(单独使用前后都行)
System.out.println(x); // 6
int y = 5;
int result = ++y; // 先加后用,result=6, y=6
int result2 = y++; // 先用后加,result2=6, y=7
赋值和关系运算符:
int num = 10;
num += 5; // 等价 num = num + 5; 现在 num 是 15
boolean r1 = 10 == 10; // true
boolean r2 = 10 != 5; // true
boolean r3 = 3 > 5; // false
逻辑运算符:拼接多个条件判断
boolean b1 = (3 > 2) && (5 > 3); // true,短路与,两边都真才是真
boolean b2 = (3 > 2) || (1 > 5); // true,短路或,一边真就是真
boolean b3 = !true; // false
三元运算符:条件 ? 值1 : 值2
int score = 75;
String result = score >= 60 ? "及格" : "不及格"; // 及格
类型转换:
// 自动转换:小范围 -> 大范围
double d = 10; // int 自动变 double
// 强制转换:大范围 -> 小范围 (可能丢失精度)
int i = (int) 3.99; // i 是 3,小数直接砍掉
2.4 Scanner 键盘录入
让程序能接收用户的输入。
import java.util.Scanner; // 1. 导包
public class ScannerDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // 2. 创建对象
System.out.println("请输入你的名字:");
String name = sc.next(); // 3. 接收字符串(不含空格)
System.out.println("请输入你的年龄:");
int age = sc.nextInt(); // 接收整数
System.out.println("姓名:" + name + ",年龄:" + age);
}
}
其他接收:nextDouble() 小数,nextLine() 整行字符串(会接收回车,需注意混用问题)。
2.5 方法(重要的打包工具)
方法就是把一段代码打包,起个名,以后直接调用。
public class MethodDemo {
public static void main(String[] args) {
// 调用方法
printHello();
int sum = add(5, 3);
System.out.println("和为:" + sum);
}
// 1. 无参数无返回值的方法
public static void printHello() {
System.out.println("Hello from method!");
}
// 2. 有参数有返回值的方法
public static int add(int a, int b) {
return a + b;
}
}
方法重载:同一个类中,方法名相同,参数列表不同(个数、类型、顺序),与返回值无关。
public static int add(int a, int b) { return a + b; }
public static double add(double a, double b) { return a + b; } // 重载
public static int add(int a, int b, int c) { return a + b + c; } // 也是重载
package 管理
把 Java 文件分文件夹存放,避免类名冲突。
package com.itbaizhan.study; // 必须在文件第一行
public class Student {
// ...
}
文件夹结构对应:com/itbaizhan/study/Student.java
第三章 流程控制语句(让程序活起来)
3.1 if 分支:条件判断
public class IfDemo {
public static void main(String[] args) {
int score = 85;
// 格式1:单分支
if (score >= 60) {
System.out.println("及格了");
}
// 格式2:双分支
if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
// 格式3:多分支
if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
}
}
注意事项:大括号里只有一行语句时,大括号可以省略,但不建议。
3.2 switch 分支:多值匹配
public class SwitchDemo {
public static void main(String[] args) {
int day = 3;
switch (day) {
case 1:
System.out.println("星期一");
break; // 别忘了 break,否则会穿透
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
default:
System.out.println("输入有误");
}
}
}
支持 byte, short, int, char, String, 枚举。
Java 14+ 箭头写法(无需 break,多分支可合并):
String week = switch (day) {
case 1 -> "星期一";
case 2 -> "星期二";
case 3 -> "星期三";
default -> "输入有误";
};
System.out.println(week);
3.3 for 循环:重复做事情
// 打印 1 到 5
for (int i = 1; i <= 5; i++) {
System.out.println("第" + i + "次循环");
}
练习:求 1-100 之间的偶数和
int sum = 0;
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
sum += i;
}
}
System.out.println("偶数和:" + sum); // 2550
嵌套循环:打印九九乘法表
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "*" + i + "=" + (j*i) + "\t");
}
System.out.println(); // 换行
}
3.4 while 与 do-while 循环
// while:先判断后执行
int a = 1;
while (a <= 5) {
System.out.println(a);
a++;
}
// do-while:先执行一次再判断(至少执行一次)
int b = 1;
do {
System.out.println(b);
b++;
} while (b <= 5);
3.5 break 和 continue
// break: 结束整个循环
for (int i = 1; i <= 10; i++) {
if (i == 5) break;
System.out.print(i + " "); // 打印 1 2 3 4
}
// continue: 跳过本次循环,继续下一次
for (int i = 1; i <= 5; i++) {
if (i == 3) continue;
System.out.print(i + " "); // 打印 1 2 4 5
}
3.6 Random 随机数
import java.util.Random;
public class RandomDemo {
public static void main(String[] args) {
Random r = new Random();
int number = r.nextInt(100); // 0 到 99 的随机整数
System.out.println(number);
// 猜数字小游戏(简单版)
int guessNum = r.nextInt(100) + 1; // 1-100
// ... 可结合循环和扫描器完成猜数字
}
}
第四章 数组(一堆数据的容器)
4.1 数组的定义与初始化
// 静态初始化:已知元素
int[] arr1 = new int[]{10, 20, 30};
int[] arr2 = {40, 50, 60}; // 简写形式
String[] names = {"张三", "李四", "王五"};
4.2 访问元素和遍历
索引从 0 开始。
int[] arr = {10, 20, 30};
System.out.println(arr[0]); // 10
System.out.println(arr.length); // 3,数组长度
// 遍历
for (int i = 0; i < arr.length; i++) {
System.out.println("第" + i + "个元素:" + arr[i]);
}
4.3 常见案例
求最大值:
int[] scores = {85, 92, 78, 99, 63};
int max = scores[0];
for (int i = 1; i < scores.length; i++) {
if (scores[i] > max) {
max = scores[i];
}
}
System.out.println("最高分:" + max);
数组反转(头尾交换):
int[] arr = {1, 2, 3, 4, 5};
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 打印反转后:5 4 3 2 1
4.4 动态初始化
int[] arr = new int[5]; // 默认值都是 0
arr[0] = 10;
arr[1] = 20;
// ...
4.5 数组常见问题
- 索引越界:
arr[5]当长度只有 5 时(最大索引 4),抛出ArrayIndexOutOfBoundsException - 空指针:
int[] arr = null; arr[0] = 10;抛出NullPointerException
4.6 二维数组(表格数据)
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 遍历
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
输出:
1 2 3
4 5 6
7 8 9
第五章 面向对象基础(编程思维升级)
5.1 类与对象
类是模板,对象是具体产品。
// 学生类
public class Student {
// 属性(成员变量)
String name;
int age;
// 行为(成员方法)
public void study() {
System.out.println(name + "正在学习...");
}
public void doHomework() {
System.out.println(name + "正在写作业,年龄:" + age);
}
}
创建并使用对象:
public class Test {
public static void main(String[] args) {
Student stu = new Student(); // 创建对象
stu.name = "小明"; // 赋值属性
stu.age = 18;
stu.study(); // 调用方法
stu.doHomework();
}
}
5.2 封装与 this
封装:用 private 隐藏属性,通过公共的 get/set 方法访问。
public class Person {
private String name; // 私有
private int age;
// setter 方法:设置值
public void setName(String name) {
this.name = name; // this 指当前对象
}
// getter 方法:获取值
public String getName() {
return name;
}
public void setAge(int age) {
if (age >= 0 && age <= 150) {
this.age = age;
} else {
System.out.println("年龄不合法");
}
}
public int getAge() {
return age;
}
}
使用:
Person p = new Person();
p.setName("小红");
p.setAge(20);
System.out.println(p.getName() + " " + p.getAge());
5.3 构造方法
构造方法是对象创建时自动调用的方法,用来初始化对象。
public class Student {
private String name;
private int age;
// 无参构造(若不写,系统默认给;一旦手写有参,建议补上无参)
public Student() {}
// 有参构造
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// getter/setter 省略...
}
创建对象:
Student s1 = new Student(); // 调用无参构造
Student s2 = new Student("小刚", 20); // 调用有参构造
5.4 标准 JavaBean
一个标准的 JavaBean 满足:
- 类公开
- 属性私有
- 提供无参和全参构造
- 提供 getter 和 setter
可以按照这个模板写大多数实体类。
5.5 static 关键字
static 表示“属于类”,所有对象共享。
public class Chinese {
static String country = "中国"; // 共享属性
String name; // 每个对象独有
public Chinese(String name) {
this.name = name;
}
public static void showCountry() {
System.out.println("国籍:" + country);
// 静态方法不能直接访问非静态成员 name
}
}
使用:
Chinese c1 = new Chinese("小明");
Chinese c2 = new Chinese("小红");
System.out.println(c1.country); // 中国
System.out.println(c2.country); // 中国
Chinese.country = "中华人民共和国"; // 推荐用类名访问
System.out.println(c1.country); // 中华人民共和国
5.6 工具类的制作(私有构造方法)
在日常开发中,我们经常需要编写一些只包含静态方法的工具类(例如 Math、Arrays 类)。与 C# 可以直接定义 public static class 不同,Java 不支持顶级的静态类。
为了防止其他开发者误用 new 关键字实例化这些仅仅提供静态方法的工具类,标准的做法是私有化构造方法。
public final class ArrayUtils {
// 1. 私有化无参构造,隐藏实例化入口
private ArrayUtils() {
// 推荐做法:抛出异常,防止在类内部或通过反射机制被意外调用
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
// 2. 暴露静态方法
public static int getMax(int[] arr) {
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) max = arr[i];
}
return max;
}
}
final修饰类:防止该类被继承,从而避免子类在内部实例化或破坏设计。private构造方法:禁止外部直接new ArrayUtils()。
第六章 面向对象高级(能力进阶)
6.1 继承
继承就是子承父业,减少重复代码,使用 extends。
// 父类
public class Animal {
String name;
public void eat() {
System.out.println(name + "吃东西");
}
}
// 子类
public class Dog extends Animal {
public void bark() {
System.out.println(name + "汪汪叫");
}
}
测试:
Dog dog = new Dog();
dog.name = "旺财";
dog.eat(); // 来自父类
dog.bark(); // 自己独有
方法重写:子类觉得父类方法不满足需求,就重写一个。
public class Cat extends Animal {
@Override // 注解,检查是否正确重写
public void eat() {
System.out.println(name + "优雅地吃鱼");
}
}
super 关键字调用父类成员:
public class Son extends Father {
public void show() {
super.show(); // 先调用父类的 show
System.out.println("子类的扩展");
}
}
继承中的构造方法:子类构造器第一行默认有 super() 调用父类无参构造。如果父类只有有参构造,子类必须手动 super(参数)。
6.2 final 关键字
final class:不能被继承final 方法:不能被重写final 变量:变成常量,只能赋值一次(基本类型值不变,引用类型地址不变)
6.3 抽象类
抽象类不能实例化,专门当爹用,定义一些抽象方法让子类必须实现。
public abstract class Shape {
public abstract double area(); // 没有方法体
}
public class Circle extends Shape {
double r;
public Circle(double r) { this.r = r; }
@Override
public double area() {
return Math.PI * r * r;
}
}
6.4 接口
接口是一种行为规范:规定「能做什么」,由实现类决定「怎么做」。Java 8 起接口除抽象方法外,还可以包含 default 默认方法 和 static 静态方法。
public interface Flyable {
void fly(); // 默认 public abstract
default void glide() {
System.out.println("滑翔辅助");
}
static void showTip() {
System.out.println("实现 fly() 即可");
}
}
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("鸟儿扇动翅膀飞");
}
}
public class Airplane implements Flyable {
@Override
public void fly() {
System.out.println("飞机引擎驱动飞");
}
}
一个类可以实现多个接口:class SuperMan implements Flyable, Swimable { }
6.5 多态
多态就是 父类引用指向子类对象。
Animal a = new Dog(); // 编译看左边(Animal),运行看右边(Dog)
a.eat(); // 调用的是 Dog 重写后的 eat
// a.bark(); // 编译错误,不能调用子类独有方法
转型:
if (a instanceof Dog) {
Dog d = (Dog) a; // 向下转型
d.bark();
}
6.6 内部类与 Lambda 表达式
匿名内部类:因为没有名字,直接 new 接口/抽象类,重写方法。
Flyable f = new Flyable() {
@Override
public void fly() {
System.out.println("匿名内部类的方式飞");
}
};
f.fly();
Lambda 表达式:简化匿名内部类,只适用于函数式接口(只有一个抽象方法的接口)。
Flyable f2 = () -> { System.out.println("Lambda 方式飞"); };
f2.fly();
// 省略更多:若只有一行代码,大括号和分号也可省略
Flyable f3 = () -> System.out.println("极简飞");
第七章 String 与 StringBuilder
7.1 String 是什么
String 表示字符串,也就是一串字符。在 Java 里,字符串不是基本类型,而是一个类,位于 java.lang 包下,所以可以直接使用。
String s1 = "hello";
String s2 = "Java";
String s3 = new String("world");
常见创建方式:
String s = "abc";:最常用,推荐写法。new String("abc"):也能创建,但一般没必要。
String 的核心特点:不可变
字符串一旦创建,内容就不能被直接修改。看起来像“修改”,本质上是生成了新字符串对象。
String name = "Tom";
name = name + " Lee";
System.out.println(name); // Tom Lee
上面不是把原来的 "Tom" 改掉了,而是让变量 name 指向了一个新字符串。
7.2 字符串常量池与创建差异
Java 为了节省内存,对字符串字面量做了复用,这个区域通常叫字符串常量池。
String a = "abc";
String b = "abc";
String c = new String("abc");
System.out.println(a == b); // true,指向常量池中同一个字符串对象
System.out.println(a == c); // false,c 是 new 出来的新对象
System.out.println(a.equals(c)); // true,内容一样
重点:
- 直接写
"abc",会优先复用常量池中的对象。 new String("abc")会在堆内存中再创建新对象。==在这里体现的是“是否为同一个对象”,不是“内容是否相同”。
7.3 String 常用方法
String 在业务开发中非常常见,下面这些方法最常用:
| 方法 | 作用 | 示例 |
|---|---|---|
length() | 获取长度 | "abc".length() 得到 3 |
charAt(i) | 获取指定位置字符 | "abc".charAt(1) 得到 'b' |
equals(str) | 比较内容是否相同 | "abc".equals("abc") |
equalsIgnoreCase(str) | 忽略大小写比较 | "java".equalsIgnoreCase("JAVA") |
substring(begin, end) | 截取子串,左闭右开 | "abcdef".substring(1, 4) 得到 "bcd" |
contains(str) | 是否包含子串 | "hello".contains("ll") |
startsWith(str) | 是否以指定内容开头 | "java".startsWith("ja") |
endsWith(str) | 是否以指定内容结尾 | "a.txt".endsWith(".txt") |
replace(old, new) | 替换内容 | "2024-01".replace("-", "/") |
split(regex) | 按规则拆分字符串 | "a,b,c".split(",") |
trim() | 去掉首尾空白 | " hi ".trim() |
toUpperCase() | 转大写 | "java".toUpperCase() |
toLowerCase() | 转小写 | "JAVA".toLowerCase() |
代码示例:
public class StringMethodDemo {
public static void main(String[] args) {
String str = " Hello Java ";
System.out.println(str.length());
System.out.println(str.charAt(2));
System.out.println(str.trim());
System.out.println(str.contains("Java"));
System.out.println(str.substring(2, 7));
System.out.println(str.replace("Java", "JDK"));
}
}
7.4 比较字符串时的常见坑
上面的方法表已经列出常用 API,这里专门补充初学者最容易踩坑的几个点。
1. == 比较地址,equals() 比较内容
String s1 = "admin";
String s2 = new String("admin");
System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2)); // true
2. 注意空指针问题
如果变量可能为 null,直接调用 str.equals("abc") 可能报错。
String role = null;
// System.out.println(role.equals("admin")); // 可能抛出空指针异常
System.out.println("admin".equals(role)); // 更安全
3. split 的参数是正则表达式
像 .、| 这些字符在正则里有特殊含义,需要转义。
String ip = "192.168.1.1";
String[] arr = ip.split("\\.");
7.5 为什么循环拼接字符串不推荐直接用 +
前面在运算符部分已经讲过 + 可以做字符串拼接,这里补充它在性能上的注意点。
少量拼接写 + 很方便,但在循环里频繁拼接会产生很多中间字符串对象,性能较差。
String result = "";
for (int i = 0; i < 5; i++) {
result = result + i;
}
System.out.println(result);
因为 String 不可变,每次 + 都可能创建新对象。循环次数一大,开销就明显了。
这类场景更适合使用 StringBuilder。
7.6 StringBuilder 的作用
StringBuilder 是一个可变字符容器,适合频繁拼接、修改字符串内容的场景。
StringBuilder sb = new StringBuilder();
sb.append("Java");
sb.append(" ");
sb.append("Study");
System.out.println(sb); // Java Study
System.out.println(sb.toString()); // 转成 String
特点:
- 内容可变,追加和修改效率比频繁
String +更高。 - 位于
java.lang包下,也不需要手动导包。 - 最终如果要得到字符串结果,调用
toString()。
7.7 StringBuilder 常用方法
| 方法 | 作用 |
|---|---|
append(data) | 在末尾追加内容 |
insert(index, data) | 在指定位置插入 |
delete(start, end) | 删除指定范围,左闭右开 |
replace(start, end, str) | 替换指定范围内容 |
reverse() | 反转字符顺序 |
length() | 获取当前字符个数 |
toString() | 转成 String |
示例:
public class StringBuilderDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("abc");
sb.append("123");
sb.insert(3, "-");
sb.replace(0, 3, "XYZ");
System.out.println(sb); // XYZ-123
System.out.println(sb.reverse()); // 321-ZYX
System.out.println(sb.reverse()); // XYZ-123
System.out.println(sb.toString()); // XYZ-123
}
}
7.8 String、StringBuilder、StringBuffer 的区别
| 类型 | 是否可变 | 线程安全 | 适用场景 |
|---|---|---|---|
String | 不可变 | 安全 | 字符串常量、少量拼接、比较和传参 |
StringBuilder | 可变 | 不保证线程安全 | 单线程下频繁拼接,最常用 |
StringBuffer | 可变 | 线程安全 | 多线程下的字符串修改,现在线程内场景较少用 |
初学阶段先记住:
- 普通字符串处理,使用
String。 - 循环拼接、批量拼接,优先使用
StringBuilder。 StringBuffer知道它是线程安全版本即可。
7.9 实战案例:把数组拼成字符串
需求:把 {"张三", "李四", "王五"} 拼成 [张三, 李四, 王五]。
public class JoinNamesDemo {
public static void main(String[] args) {
String[] names = {"张三", "李四", "王五"};
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < names.length; i++) {
sb.append(names[i]);
if (i != names.length - 1) {
sb.append(", ");
}
}
sb.append("]");
System.out.println(sb.toString());
}
}
这种“循环中持续追加”的题目,是 StringBuilder 最经典的使用场景。
这里故意没有直接使用 String.join(),是因为当前这篇文章的重点是让你先掌握 StringBuilder 的核心使用方式。等你进入后续的常用 API 和集合章节后,再学习更简洁的拼接写法会更自然。
7.10 本章先记住这几件事
String是类,不是基本类型,而且内容一旦创建就不能直接修改。- 比较字符串内容用
equals(),不要用==。 - 变量可能为
null时,推荐写"固定值".equals(变量)。 - 循环里频繁拼接字符串,优先使用
StringBuilder。 StringBuffer先知道它是线程安全版本即可,初学阶段不用深挖。
如果你还想继续学习 String.join()、StringJoiner、String.format()、formatted() 这类字符串处理 API,可以接着看《Java 常用 API 与字符串、时间处理》;如果想学习 Collectors.joining(),可以在集合文档的 Stream 小节继续往下看。