本教程面向大学一年级学生,强调 Java 的灵魂——面向对象编程(OOP),并覆盖核心类库、集合、异常、Lambda/Stream、并发、JDBC 与工程实践。学完后你将能独立设计与实现中等规模的 Java 程序,并理解企业级开发的完整工具链。
在动手写代码之前,先建立全局认知 —— Java 的本质、JVM 的运行原理,以及一条循序渐进的学习路线。
Java 由 Sun Microsystems 公司于 1995 年发布,2010 年后由 Oracle 维护。它是一门面向对象、跨平台、强类型的通用编程语言。
一句话总结:Java 是工业界应用最广的 OOP 语言之一 —— 学好它,能打开从后端到大数据的整片职业空间。
Java 程序不是直接编译成机器码,而是先编译成 字节码(.class),再由 JVM 翻译成机器码执行。这就是"一次编译,到处运行"的秘密。
| 名称 | 含义 | 关系 |
|---|---|---|
| JVM | Java 虚拟机,真正执行字节码 | JRE 的一部分 |
| JRE | Java 运行时环境 = JVM + 标准库 | JDK 的一部分 |
| JDK | Java 开发工具包 = JRE + 编译器 + 工具 | 开发人员安装 |
搭好工具链,写下你的第一个 HelloWorld.java。
| JDK 发行版 | 特点 | 推荐场景 |
|---|---|---|
| Oracle JDK | 官方版本,商业使用需付费 | 商业项目 |
| OpenJDK (Adoptium) | 免费开源,主流选择 | 教学 / 大多数项目(推荐) |
| Microsoft OpenJDK | 微软优化版 | Windows 用户 |
| Amazon Corretto | 亚马逊维护 | 云端部署 |
JAVA_HOME 指向 JDK 安装目录;将 %JAVA_HOME%\bin(Windows)或 $JAVA_HOME/bin(macOS/Linux)加入 PATH。验证:java -version 与 javac -version。public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}public class HelloWorld:声明一个公共类,文件名必须为 HelloWorld.java;public static void main(String[] args):主方法,JVM 的入口;
public:JVM 可访问;static:不需创建对象即可调用;void:无返回值;String[] args:命令行参数;System.out.println(...):把字符串打印到标准输出,并换行。# 1. 用编辑器写 HelloWorld.java(注意:文件名必须与 public class 同名)
$ vim HelloWorld.java
# 2. 编译:javac 把 .java 编译成 .class
$ javac HelloWorld.java
$ ls
HelloWorld.class HelloWorld.java
# 3. 运行:java 启动 JVM,加载字节码并执行
$ java HelloWorld
Hello, World!
# 常见编译错误示例
$ java HelloWorld.java # ❌ 不要加 .java 后缀
错误: 找不到或无法加载主类 HelloWorld.javaJava 程序的基本组成:包、类、方法、语句 —— 每个 Java 程序至少包含一个类。
// package 语句(可选):类的所属包
package com.example.lesson;
// import 语句(可选):引入其他包的类
import java.util.Scanner;
// public class:每个 .java 文件最多一个 public 类,文件名必须与之相同
public class Main {
// main 方法:程序入口
public static void main(String[] args) {
// 语句
System.out.println("Hello");
}
}// 单行注释:到行尾结束
/*
* 多行注释:跨越多行
* 可用于临时屏蔽代码块
*/
/**
* 文档注释(Javadoc):用于生成 API 文档
* @param x 参数说明
* @return 返回值说明
*/
public int foo(int x) { return x * 2; }// 变量:值可以变
int age = 18;
double score = 95.5;
char grade = 'A';
String name = "Java";
// 常量:用 final 修饰(必须初始化)
final double PI = 3.14159;
final int MAX = 100;
// PI = 3.14; // ❌ 编译错误:不能修改 final 变量import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 输出
System.out.print("不换行");
System.out.println("自动换行");
System.out.printf("姓名=%s, 年龄=%d\n", "Alice", 20);
// 输入(从标准输入读)
Scanner sc = new Scanner(System.in);
System.out.print("请输入姓名:");
String name = sc.nextLine(); // 读整行(含空格)
System.out.print("请输入年龄:");
int age = sc.nextInt(); // 读整数
System.out.printf("你好 %s,你 %d 岁\n", name, age);
sc.close();
}
}Java 是强类型语言:每个变量都有明确的类型。掌握 8 种基本类型,是后续学习的基石。
| 类型 | 含义 | 大小 | 默认值 | 示例 |
|---|---|---|---|---|
| byte | 字节型 | 1 | 0 | byte b = 100; |
| short | 短整型 | 2 | 0 | short s = 1000; |
| int | 整型(最常用) | 4 | 0 | int n = 100000; |
| long | 长整型 | 8 | 0L | long l = 100L; |
| float | 单精度浮点 | 4 | 0.0f | float f = 3.14f; |
| double | 双精度浮点(默认) | 8 | 0.0d | double d = 3.14; |
| char | 字符(UTF-16 单元) | 2 | '\u0000' | char c = 'A'; |
| boolean | 布尔 | 1 | false | boolean b = true; |
String、数组、对象;int a = 10; // 基本类型,存 10
String s = "Hello"; // 引用类型,存的是字符串对象的地址
int b = a; // 值拷贝:b 也等于 10
String t = s; // 地址拷贝:t 与 s 指向同一对象// 1) 自动转换:小 → 大(安全)
int i = 100;
double d = i; // 100 → 100.0
// 2) 强制转换:大 → 小(可能丢失精度)
double d2 = 3.99;
int i2 = (int) d2; // 3(直接截断,不四舍五入)
// 3) 字符串与数字互转
String s1 = String.valueOf(42); // int → String
int i3 = Integer.parseInt("123"); // String → int与 C/C++ 类似,Java 的运算符包括:算术、关系、逻辑、位运算、赋值、三元等。这里列出 Java 特有注意点:
10 / 3 = 3(不是 3.33);10 % 3 = 1;== 对基本类型比较值,对引用类型比较地址;&&、||;& | ^ ~ << >> >>>(>>> 是 Java 特有的无符号右移)。7 / 2 的结果是?(int) 3.99 的结果是?与 C/C++ 基本一致;Java 14+ 引入switch 表达式,让代码更简洁。
if (score >= 90) {
grade = "A";
} else if (score >= 80) {
grade = "B";
} else if (score >= 60) {
grade = "C";
} else {
grade = "D";
}// 传统 switch:每个 case 需要 break
switch (day) {
case 1: print("Mon"); break;
case 2: print("Tue"); break;
default: print("Other");
}
// Java 14+ switch 表达式:返回值,更安全(无穿透)
String name = switch (day) {
case 1 -> "Mon";
case 2 -> "Tue";
case 3, 4, 5 -> "Midweek"; // 多值合并
default -> "Weekend";
};// while
int i = 0;
while (i < 5) {
System.out.println(i++);
}
// do-while:至少执行一次
int n;
do {
System.out.print("输入正数:");
n = sc.nextInt();
} while (n <= 0);
// 经典 for
for (int j = 0; j < 5; j++) {
System.out.println(j);
}
// 增强 for(foreach):遍历数组或集合
int[] nums = {1, 2, 3, 4, 5};
for (int x : nums) {
System.out.println(x);
}import java.util.Scanner;
import java.util.Random;
public class GuessNumber {
public static void main(String[] args) {
Random r = new Random();
int target = r.nextInt(100) + 1; // 1~100
Scanner sc = new Scanner(System.in);
int guess, tries = 0;
do {
System.out.print("猜一个 1-100 的数:");
guess = sc.nextInt();
tries++;
if (guess > target) System.out.println("大了!");
else if (guess < target) System.out.println("小了!");
} while (guess != target);
System.out.printf("用了 %d 次猜中!\n", tries);
}
}数组是同类型元素的容器;String 是 Java 专门设计的不可变字符串类。
// 三种声明方式(推荐第一种)
int[] scores = new int[5]; // 默认 0
int[] ages = {18, 20, 22}; // 静态初始化
String[] names = new String[]{"A","B"};
// 访问 / 遍历
ages[0] = 25;
System.out.println(ages.length); // 数组长度(属性,非方法)
for (int x : ages) {
System.out.println(x);
}
// Arrays 工具类
import java.util.Arrays;
Arrays.sort(ages); // 升序排序
System.out.println(Arrays.toString(ages));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();
}String 是 Java 最重要的类之一:不可变(每次"修改"都创建新对象)。
String s = "Hello, Java!";
// 常用方法
System.out.println(s.length()); // 12
System.out.println(s.charAt(0)); // 'H'
System.out.println(s.substring(0, 5)); // "Hello"
System.out.println(s.indexOf("Java")); // 7
System.out.println(s.contains("Java")); // true
System.out.println(s.startsWith("Hi")); // false
System.out.println(s.replace("Java", "World")); // 新字符串对象
System.out.println(s.split(", ")[0]); // "Hello"
// 字符串比较:必须用 equals
String a = "java", b = "JAVA";
a.equals(b); // false(区分大小写)
a.equalsIgnoreCase(b); // true
// a == b // ❌ 比较地址,可能为 false频繁拼接字符串时,用 StringBuilder 比 String 高效得多。
// ❌ 低效:每次 + 都创建新 String 对象
String s = "";
for (int i = 0; i < 1000; i++) s = s + i;
// ✔ 高效:使用 StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) sb.append(i);
String result = sb.toString();方法 = C/C++ 中的"函数"。Java 中所有方法都必须属于类。
public class MethodDemo {
// 无返回值
public static void sayHi(String name) {
System.out.println("Hi, " + name);
}
// 有返回值
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 sum(int... nums) {
int total = 0;
for (int n : nums) total += n;
return total;
}
public static void main(String[] args) {
sayHi("Alice");
System.out.println(add(3, 5)); // 8
System.out.println(sum(1, 2, 3, 4, 5)); // 15
}
}Java 只有值传递。对于引用类型,传的是"地址值的拷贝"——修改对象内容会影响原对象,但改变形参指向不影响原引用。
// 1) 基本类型:完全拷贝,互不影响
static void swapInt(int a, int b) {
int t = a; a = b; b = t; // 仅在方法内交换
}
// 2) 引用类型:可以修改对象内容,但不能改变原引用指向
static void modify(int[] arr) {
arr[0] = 999; // ✔ 修改原数组元素
}static long factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// Fibonacci:朴素递归效率极低,实际应用应改用迭代
static long fib(int n) {
if (n < 2) return n;
return fib(n - 1) + fib(n - 2);
}
// 迭代版 Fibonacci:O(n) 时间,O(1) 空间
static long fibIter(int n) {
if (n < 2) return n;
long a = 0, b = 1;
for (int i = 2; i <= n; i++) {
long c = a + b; a = b; b = c;
}
return b;
}本章是整个 Java 课程的核心。请把更多时间放在这里——把每一节都动手写一遍。
把程序看作一系列函数调用,数据与行为分离。
// 单独的数据 + 单独的函数
struct Student { char name[32]; int age; };
void setAge(struct Student* s, int a) {
s->age = a;
}把数据和行为封装进同一个"类",对象之间通过消息协作。
// 数据 + 行为打包在一起
class Student {
private String name;
private int age;
public void setAge(int a) { this.age = a; }
public int getAge() { return age; }
}OOP 三大特性:封装(数据隐藏 + 行为内聚) · 继承(代码复用 + 类型扩展) · 多态(同一消息,不同响应)。这三大特性是 OOP 思想的精髓,Java 在语法层面对它们的支持堪称典范。
类 = 对象的模板。Java 中所有代码都必须写在类里(除了少数注释和包声明)。
public class Student {
// 成员变量(字段)—— 推荐 private
private String name;
private int age;
private double score;
// 构造方法(Constructor):用于初始化对象
public Student() {
this("Unknown", 0, 0.0); // 调用其他构造
}
public Student(String name, int age) {
this(name, age, 0.0);
}
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
// 公开方法
public void study() {
System.out.println(name + " 在学习");
}
public void printInfo() {
System.out.printf("%s, %d 岁, %.1f 分%n", name, age, score);
}
}public class Main {
public static void main(String[] args) {
// 创建对象:new 调用构造方法
Student s1 = new Student(); // 调用无参构造
Student s2 = new Student("Alice", 20, 95.5); // 调用带参构造
s2.study();
s2.printInfo();
}
}this.name = name),也可用于在一个构造方法中调用另一个(this(...))。封装的核心:把数据藏起来,把方法暴露出去。外部只能通过公开方法访问数据,从而保证数据有效性。
| 修饰符 | 本类 | 同包 | 子类 | 其他类 |
|---|---|---|---|---|
| private | ✔ | ✘ | ✘ | ✘ |
| default | ✔ | ✔ | ✘ | ✘ |
| protected | ✔ | ✔ | ✔ | ✘ |
| public | ✔ | ✔ | ✔ | ✔ |
public class Account {
private String owner;
private double balance; // 余额:必须保持非负
public Account(String owner, double init) {
this.owner = owner;
this.balance = init >= 0 ? init : 0;
}
// 通过 getter 读,通过 setter 受控地写
public String getOwner() { return owner; }
public double getBalance() { return balance; }
// 业务方法:体现"行为"
public void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("金额必须为正");
balance += amount;
}
public void withdraw(double amount) {
if (amount > balance) throw new IllegalArgumentException("余额不足");
balance -= amount;
}
}private;必要时提供 public getter/setter;数据校验放在 setter 或业务方法中。public class Counter {
public static int totalCount = 0; // 类变量:所有对象共享
public static final String VERSION = "1.0"; // 类常量
private int id;
public Counter() {
totalCount++;
this.id = totalCount;
}
// 静态方法:不能访问实例成员
public static int getTotal() { return totalCount; }
}
// 使用
System.out.println(Counter.VERSION); // 1.0 (类名.常量)
new Counter();
new Counter();
System.out.println(Counter.getTotal()); // 2static 表示"类级别的"(属于类,不属于对象);final 表示"不可修改"。两者经常组合成"类常量" public static final。Java 只支持单继承(一个类只能 extends 一个父类)。多继承通过接口实现。
// 父类
public class Person {
protected String name;
protected int age;
public Person(String name, int age) {
this.name = name; this.age = age;
}
public void sayHi() {
System.out.println("Hi, 我叫 " + name);
}
}
// 子类
public class Student extends Person {
private String school;
public Student(String name, int age, String school) {
super(name, age); // 调用父类构造(必须第一句)
this.school = school;
}
@Override // 方法重写(覆盖父类)
public void sayHi() {
super.sayHi(); // 调用父类版本
System.out.println("我在 " + school + " 上学");
}
}子类可以重写父类的方法,提供自己的实现。@Override 注解让编译器帮你检查是否真的覆盖了父类方法。
class Animal {
public void sound() {
System.out.println("...");
}
}
class Dog extends Animal {
@Override // 强烈推荐:编译器会校验
public void sound() {
System.out.println("汪汪!");
}
}
class Cat extends Animal {
@Override
public void sound() {
System.out.println("喵喵!");
}
}static、private、final 方法。多态是 OOP 的精髓:父类引用指向子类对象,调用方法时执行子类版本。
public class PolymorphismDemo {
public static void main(String[] args) {
// 父类引用 → 子类对象
Animal a1 = new Dog();
Animal a2 = new Cat();
makeSound(a1); // 汪汪!
makeSound(a2); // 喵喵!
// 多态数组:处理一组"形状"
Animal[] animals = {new Dog(), new Cat(), new Animal()};
for (Animal a : animals) a.sound();
}
// 接受父类引用:实际执行子类的方法
static void makeSound(Animal a) {
a.sound();
}
}包含抽象方法(没有实现的方法)的类必须用 abstract 修饰,不能直接实例化。
public abstract class Shape {
protected String color;
public Shape(String color) { this.color = color; }
// 抽象方法:只有签名,没有实现
public abstract double area();
public abstract double perimeter();
// 普通方法可以保留
public String getColor() { return color; }
}
public class Circle extends Shape {
private double r;
public Circle(String color, double r) {
super(color); this.r = r;
}
@Override public double area() { return 3.14159 * r * r; }
@Override public double perimeter() { return 2 * 3.14159 * r; }
}
// Shape s = new Shape(); // ❌ 不能实例化抽象类
Shape s = new Circle("Red", 2.0); // ✔ 多态接口定义"做什么",类实现"怎么做"。一个类可以实现多个接口(弥补 Java 单继承)。
// 接口:只声明"做什么",不写"怎么做"
public interface Flyable {
void fly(); // 默认 public abstract
// Java 8+ 默认方法(有实现)
default void land() {
System.out.println("着陆");
}
// Java 8+ 静态方法
static boolean canFly(Flyable f) {
return f != null;
}
}
public interface Swimmable {
void swim();
}
// 类实现多个接口(弥补 Java 单继承)
public class Duck extends Animal implements Flyable, Swimmable {
@Override public void fly() { System.out.println("鸭子飞"); }
@Override public void swim() { System.out.println("鸭子游"); }
}Java 中所有类都直接或间接继承自 java.lang.Object。掌握它的三个核心方法:
@Override
public String toString() { // 对象的字符串表示
return "Student{name=" + name + ", age=" + age + "}";
}
@Override
public boolean equals(Object o) { // 内容相等
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student s = (Student) o;
return 18 == s.age && name.equals(s.name);
}
@Override
public int hashCode() { // 哈希码(与 equals 配对)
return Objects.hash(name, age);
}equals 必须同时重写 hashCode —— 否则对象在 HashMap/HashSet 中行为异常。// 枚举:一组固定常量的类型安全写法
public enum Color {
RED, GREEN, BLUE;
public String rgb() { return this.name(); }
}
// 使用
for (Color c : Color.values()) {
System.out.println(c + " = " + c.rgb());
}
// Record(Java 16+):不可变数据类,自动生成 equals/hashCode/toString
public record Point(int x, int y) { }
Point p = new Point(3, 4); // p.toString() = "Point[x=3, y=4]"JDK 自带的基础类 —— 不学这些,你的程序会写得笨拙。
8 种基本类型各有对应的包装类,用于把基本类型当作对象使用(如放入集合)。
| 基本类型 | 包装类 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
// 自动装箱:int → Integer
Integer a = 10; // 等价于 Integer.valueOf(10)
// 自动拆箱:Integer → int
int b = a; // 等价于 a.intValue()
// 字符串与整数互转
String s = String.valueOf(42);
int n = Integer.parseInt("123");
// BigDecimal:金融计算(避免 double 精度问题)
BigDecimal money = new BigDecimal("0.1");
BigDecimal total = money.add(money).add(money); // 0.3(精确)// Math
Math.abs(-5); // 5
Math.max(3, 7); // 7
Math.sqrt(16); // 4.0
Math.pow(2, 10); // 1024.0
Math.random(); // [0, 1) 随机数
// Random
Random r = new Random();
int x = r.nextInt(100); // [0, 100)
double y = r.nextDouble();
// System
System.out.println("标准输出");
System.err.println("标准错误");
System.out.printf("当前时间:%tT%n", System.currentTimeMillis());
// System.exit(0); // 退出 JVMJava 用异常对象把错误处理从主逻辑中分离,让程序更健壮。
try {
// 可能出错的代码
int result = 10 / 0;
} catch (ArithmeticException e) { // 捕获特定异常
System.err.println("数学错误:" + e.getMessage());
} catch (Exception e) { // 兜底:捕获更宽泛
System.err.println("其它错误:" + e.getMessage());
} finally {
// 无论是否出错都执行(资源清理)
System.out.println("结束");
}// 1) 自定义异常类
public class InsufficientFundsException extends Exception {
private double shortage;
public InsufficientFundsException(String msg, double shortage) {
super(msg);
this.shortage = shortage;
}
public double getShortage() { return shortage; }
}
// 2) 抛出异常(throw)与声明(throws)
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance)
throw new InsufficientFundsException("余额不足", amount - balance);
balance -= amount;
}自动关闭实现了 AutoCloseable 的资源,比手写 finally 干净得多。
// ❌ 传统写法:手动关闭,容易遗漏
Scanner sc = null;
try {
sc = new Scanner(new File("data.txt"));
// ...
} finally {
if (sc != null) sc.close();
}
// ✔ 现代写法:try-with-resources
try (Scanner sc = new Scanner(new File("data.txt"));
FileWriter w = new FileWriter("out.txt")) {
// sc 与 w 会在 try 结束时自动关闭
}泛型让"一份代码处理多种数据类型"成为可能,且编译器能检查类型错误。
// 泛型类:T 是类型参数
public class Box<T> {
private T value;
public Box(T v) { this.value = v; }
public T get() { return value; }
}
Box<String> bs = new Box<>("hi"); // T = String
Box<Integer> bi = new Box<>(42); // T = Integer
// 泛型方法
public static <T> T first(List<T> list) {
return list.get(0);
}
// 常见类型参数约定
// T = Type, E = Element, K = Key, V = Value, R = ReturnList<Integer> intList = Arrays.asList(1, 2, 3);
List<Number> numList = Arrays.asList(1.5, 2.5);
// ? extends T:上界,能读不能写
public static double sum(List<? extends Number> list) {
double s = 0;
for (Number n : list) s += n.doubleValue();
return s;
}
// ? super T:下界,能写不能读
public static void addInts(List<? super Integer> list) {
list.add(42); // 可以添加 Integer
}Java 集合(Collection Framework)是处理"一组对象"的标准答案。
import java.util.*;
List<String> list = new ArrayList<>(); // 父接口引用 + 子类实例(多态)
list.add("Alice");
list.add("Bob");
list.add("1", "Carol"); // 指定下标插入
String first = list.get(0);
list.set(0, "Alex"); // 修改
list.remove("Bob"); // 按值删除
System.out.println(list.size()); // 元素个数
System.out.println(list.contains("Alice"));
// 三种遍历
for (String s : list) { System.out.println(s); }
list.forEach(System.out::println);Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 95);
scores.put("Bob", 87);
scores.put("Carol", 92);
Integer a = scores.get("Alice"); // 95,不存在则返回 null
Integer b = scores.getOrDefault("Dave", 0);
System.out.println(scores.containsKey("Alice"));
scores.remove("Bob");
// 三种遍历
scores.forEach((k, v) -> System.out.println(k + ": " + v));
for (Map.Entry<String, Integer> e : scores.entrySet()) {
System.out.println(e.getKey() + "=" + e.getValue());
}equals 和 hashCode,否则行为异常。| 场景 | 推荐 | 理由 |
|---|---|---|
| 频繁按下标读取 | ArrayList | 底层是数组,O(1) 随机访问 |
| 频繁在中间增删 | LinkedList | 链表结构,O(1) 增删(找到位置后) |
| 大多数情况 | ArrayList(默认) | 缓存局部性更好,CPU 缓存友好 |
Java 用"流(Stream)"统一读写;NIO(New IO)更现代高效。
| 类型 | 抽象类 | 常用实现 | 用途 |
|---|---|---|---|
| 字节流 | InputStream / OutputStream | FileInputStream, BufferedInputStream | 图片、音视频、二进制 |
| 字符流 | Reader / Writer | FileReader, BufferedReader | 文本文件(自动处理编码) |
import java.nio.file.*;
import java.io.*;
// 读取整个文本文件(推荐用 NIO)
String content = Files.readString(Path.of("data.txt"), StandardCharsets.UTF_8);
// 写入
Files.writeString(Path.of("out.txt"), "Hello, Java!");
// 逐行读取(推荐用 try-with-resources)
try (BufferedReader br = Files.newBufferedReader(Path.of("data.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}现代 Java 推荐使用 java.time(Java 8+);正则用 Pattern 与 Matcher。
import java.time.*;
import java.time.format.*;
LocalDate today = LocalDate.now();
LocalTime now = LocalTime.now();
LocalDateTime datetime = LocalDateTime.now();
ZonedDateTime zoned = ZonedDateTime.now();
// 计算:加 7 天、减 3 个月
LocalDate nextWeek = today.plusDays(7);
LocalDate prevMonth = today.minusMonths(3);
// 格式化
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String text = datetime.format(fmt);
// 解析
LocalDateTime parsed = LocalDateTime.parse("2024-03-15 10:30:00", fmt);import java.util.regex.*;
Pattern p = Pattern.compile("\\d{3}-\\d{4}"); // 电话号码
Matcher m = p.matcher("电话:010-1234,021-5678");
while (m.find()) {
System.out.println("找到:" + m.group());
}
// 校验邮箱
boolean ok = "[email protected]".matches("^[\\w.]+@[\\w.]+$");Java 8 引入的函数式编程能力 —— 让集合处理更简洁、更易并行。
// (参数) -> 表达式
Runnable r1 = () -> System.out.println("Hi");
Comparator<Integer> cmp = (a, b) -> a - b;
// 函数式接口(@FunctionalInterface)
// Consumer<T> 消费一个 T,无返回值
// Supplier<T> 生产一个 T,无参数
// Function<T,R> 接收 T,返回 R
// Predicate<T> 接收 T,返回 boolean
// 方法引用(Method Reference)
Function<String, Integer> len = String::length;
Consumer<String> printer = System.out::println;List<String> names = Arrays.asList("Alice", "Bob", "Carol", "Alex");
// 找出以 A 开头、长度 > 4 的名字,按字母排序,去重
List<String> result = names.stream()
.filter(s -> s.startsWith("A")) // 过滤
.filter(s -> s.length() > 4) // 再过滤
.sorted() // 排序
.distinct() // 去重
.limit(10) // 取前 10
.collect(Collectors.toList()); // 收集
// 数值统计
IntStream range = IntStream.rangeClosed(1, 100);
long sum = range.sum(); // 5050
OptionalDouble avg = range.average();collection.stream() 或 Stream.of(...)) ② 中间操作(filter / map / sorted,无副作用) ③ 终止操作(collect / forEach / count,产生结果)。Optional<String> opt = Optional.ofNullable(mayBeNull);
String result = opt
.filter(s -> s.length() > 0)
.map(String::toUpperCase)
.orElse("默认值");反射让 Java 具备"运行时自省"能力 —— 是 Spring / Hibernate 等框架的基石。
import java.lang.reflect.*;
Class<?> clazz = Student.class;
// 获取所有字段
for (Field f : clazz.getDeclaredFields()) {
System.out.println("字段:" + f.getName());
}
// 动态创建对象
Student s = (Student) clazz.getDeclaredConstructor().newInstance();
s.study();import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MyTest {
String value() default "";
}现代程序离不开并发 —— Java 在语言层内置了强大的多线程支持。
// 方式 1:继承 Thread
class MyThread extends Thread {
@Override public void run() {
System.out.println("线程运行:" + getName());
}
}
new MyThread().start();
// 方式 2:实现 Runnable(推荐,可继续继承其他类)
class MyTask implements Runnable {
public void run() {
System.out.println("任务运行");
}
}
new Thread(new MyTask()).start();
// 方式 3:Lambda(Java 8+)
new Thread(() -> System.out.println("Lambda")).start();import java.util.concurrent.*;
ExecutorService pool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
int taskId = i;
pool.submit(() -> {
System.out.println("任务 " + taskId);
});
}
pool.shutdown();class Counter {
private int count = 0;
// 同步方法
public synchronized void inc() {
count++;
}
// 同步块(更细粒度)
public void inc2() {
synchronized (this) {
count++;
}
}
}Java 内置的 java.net 让 TCP/UDP 编程变得直接。
try (ServerSocket server = new ServerSocket(8080);
Socket client = server.accept(); // 阻塞等待客户端
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true)) {
String line;
while ((line = in.readLine()) != null) {
out.println("Echo: " + line);
}
}现代 Java 项目更多用 JSON;XML 仍在企业接口、银行系统中常见。
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
// 对象 → JSON 字符串
Student s = new Student("Alice", 20);
String json = mapper.writeValueAsString(s); // {"name":"Alice","age":20}
// JSON 字符串 → 对象
Student s2 = mapper.readValue(json, Student.class);Java 通过 JDBC 与数据库交互 —— 是企业级开发的"必备技能"。
// 1) 加载驱动(Java 6+ 可省)
Class.forName("com.mysql.cj.jdbc.Driver");
// 2) 建立连接
String url = "jdbc:mysql://localhost:3306/school?useSSL=false";
try (Connection conn = DriverManager.getConnection(url, "root", "pwd")) {
// 3) 创建 PreparedStatement(推荐,防 SQL 注入)
PreparedStatement ps = conn.prepareStatement(
"SELECT * FROM students WHERE age > ?");
ps.setInt(1, 18);
// 4) 执行查询
ResultSet rs = ps.executeQuery();
while (rs.next()) {
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.printf("%s - %d%n", name, age);
}
// 5) 关闭资源(try-with-resources 自动)
}不会写测试的程序员写不出可靠的代码。
import org.junit.jupiter.api.*;
class CalculatorTest {
private Calculator calc;
@BeforeEach
void setUp() { calc = new Calculator(); }
@Test
void testAdd() {
Assertions.assertEquals(5, calc.add(2, 3));
}
@Test
void testDivideByZero() {
Assertions.assertThrows(ArithmeticException.class,
() -> calc.divide(1, 0));
}
}Java 项目的行业标准构建工具 —— 管理依赖、编译、测试、打包。
<!-- pom.xml:Maven 项目的核心配置 -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId> <--> 组织域名 -->
<artifactId>demo</artifactId> <--> 项目名 -->
<version>1.0-SNAPSHOT</version> <--> 版本 -->
<properties>
<maven.compiler.source>17</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>mvn clean compile 编译 · mvn test 跑测试 · mvn package 打包 · mvn dependency:tree 看依赖树。写出能跑的程序只是开始 —— 让代码易读、易维护才是工程能力。
| 类别 | 规则 | 示例 |
|---|---|---|
| 类 | PascalCase(名词) | StudentService |
| 方法 / 变量 | camelCase(动词 / 名词) | getName、totalCount |
| 常量 | UPPER_SNAKE_CASE | MAX_SIZE |
| 包名 | 全小写,域名反写 | com.example.school |
| 接口 | PascalCase,可加 I 前缀 | Comparable 或 IStudent |
equals;Java 自带集合框架覆盖了大部分常用结构;自定义时建议继承或参考现有接口。
class Node<T> {
T data;
Node<T> next;
Node(T d) { data = d; }
}
public class MyLinkedList<T> {
private Node<T> head;
public void addFirst(T v) {
Node<T> n = new Node<>(v);
n.next = head;
head = n;
}
public void print() {
for (Node<T> p = head; p != null; p = p.next)
System.out.print(p.data + " -> ");
System.out.println("null");
}
}以下项目按难度递进,建议至少完成前 3 个。
用 Student 类存储学生信息,ArrayList<Student> 保存多名学生;支持增删改查、按成绩排序、文件持久化。
用 HashMap 实现 O(1) 查找;支持模糊搜索;CSV 持久化。
基类 Book + 派生 TextBook、Novel、Magazine;支持借还状态机。
用 JDBC 连接 MySQL,实现学生信息的增删改查与分页。
TCP 客户端 + 多线程服务器;支持多人聊天。
Maven 多模块项目;Spring Boot / JDBC / JUnit / Git;体现工程实践能力。
写代码时随手翻一翻 —— 比每次去搜更快。
abstractassertbooleanbreakbytecasecatchcharclassconstcontinuedefaultdodoubleelseenumextendsfinalfinallyfloatforgotoifimplementsimportinstanceofintinterfacelongnativenewpackageprivateprotectedpublicrecordreturnsealedshortstaticstrictfpsuperswitchsynchronizedthisthrowthrowstransienttryvoidvolatilewhileyield
| 需求 | 推荐 |
|---|---|
| 通用序列 | ArrayList<T> |
| 中间频繁增删 | LinkedList<T> |
| 栈 / 队列 | ArrayDeque<T> |
| 优先队列 | PriorityQueue<T> |
| 去重集合 | HashSet<T>(无序)或 TreeSet<T>(有序) |
| 键值映射 | HashMap<K,V>(默认)或 TreeMap<K,V>(有序) |
| 线程安全 | ConcurrentHashMap |
// 1) 读文本文件(NIO)
String text = Files.readString(Path.of("a.txt"), StandardCharsets.UTF_8);
// 2) 写文本
Files.writeString(Path.of("a.txt"), text);
// 3) 遍历 Map
Map.entrySet().forEach(e -> log(e.getKey(), e.getValue()));
// 4) 时间测量
long t0 = System.nanoTime();
// ...
long ms = (System.nanoTime() - t0) / 1_000_000;
// 5) List → Stream → Map
Map<Integer, String> m = list.stream()
.collect(Collectors.toMap(Student::getId, Student::getName));