引言
Java作为一门历史悠久且应用广泛的编程语言,其生态系统庞大且复杂。从基础语法到高级框架,从单机应用到分布式系统,Java的学习路径漫长而富有挑战。本指南旨在为学习者提供一个从基础到精通的系统化学习路线,涵盖核心概念、高级特性以及实战技巧,帮助你构建扎实的知识体系并提升实际开发能力。
第一部分:Java基础巩固与深化
1.1 面向对象编程(OOP)核心
Java是一门纯粹的面向对象语言,深入理解OOP是掌握Java的基石。
核心概念:
- 封装:将数据(属性)和操作数据的方法(行为)捆绑在一起,并隐藏内部实现细节。
- 继承:允许子类继承父类的属性和方法,实现代码复用。
- 多态:同一接口可以有多种不同的实现方式,提高了代码的灵活性和可扩展性。
实战示例:
// 封装示例
class BankAccount {
private double balance; // 私有属性,隐藏内部状态
public BankAccount(double initialBalance) {
if (initialBalance >= 0) {
this.balance = initialBalance;
}
}
// 公共方法提供受控访问
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("存款成功,当前余额:" + balance);
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("取款成功,当前余额:" + balance);
} else {
System.out.println("取款失败,余额不足或金额无效");
}
}
public double getBalance() {
return balance;
}
}
// 继承与多态示例
abstract class Shape {
abstract double area(); // 抽象方法,强制子类实现
}
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
}
// 使用多态
public class OOPDemo {
public static void main(String[] args) {
Shape circle = new Circle(5.0);
Shape rectangle = new Rectangle(4.0, 6.0);
System.out.println("圆形面积: " + circle.area());
System.out.println("矩形面积: " + rectangle.area());
}
}
1.2 集合框架(Collections Framework)
Java集合框架是处理数据集合的核心,包括List、Set、Map等接口及其实现类。
核心接口与实现类:
- List:有序可重复集合,常用实现类:ArrayList、LinkedList
- Set:无序不可重复集合,常用实现类:HashSet、TreeSet
- Map:键值对映射,常用实现类:HashMap、TreeMap
实战示例:
import java.util.*;
public class CollectionsDemo {
public static void main(String[] args) {
// List使用示例
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Apple"); // 允许重复
System.out.println("水果列表: " + fruits);
System.out.println("第二个元素: " + fruits.get(1));
// Set使用示例
Set<String> uniqueFruits = new HashSet<>();
uniqueFruits.add("Apple");
uniqueFruits.add("Banana");
uniqueFruits.add("Apple"); // 重复元素不会被添加
System.out.println("唯一水果集合: " + uniqueFruits);
// Map使用示例
Map<String, Integer> fruitPrices = new HashMap<>();
fruitPrices.put("Apple", 5);
fruitPrices.put("Banana", 3);
fruitPrices.put("Orange", 4);
System.out.println("苹果价格: " + fruitPrices.get("Apple"));
// 遍历Map
for (Map.Entry<String, Integer> entry : fruitPrices.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
1.3 异常处理机制
Java的异常处理机制是健壮程序的基础,理解checked和unchecked异常的区别至关重要。
异常分类:
- Checked Exception:编译时异常,必须处理(如IOException)
- Unchecked Exception:运行时异常,可选处理(如NullPointerException)
实战示例:
import java.io.*;
public class ExceptionDemo {
// 自定义异常
static class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}
static class BankAccount {
private double balance;
public BankAccount(double balance) {
this.balance = balance;
}
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("余额不足,当前余额: " + balance);
}
balance -= amount;
}
}
public static void main(String[] args) {
BankAccount account = new BankAccount(100);
try {
account.withdraw(150);
} catch (InsufficientFundsException e) {
System.err.println("取款失败: " + e.getMessage());
} finally {
System.out.println("操作完成");
}
// 处理IOException
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println("文件读取错误: " + e.getMessage());
}
}
}
第二部分:Java高级特性
2.1 泛型(Generics)
泛型提供了编译时类型安全检查,避免了运行时的ClassCastException。
核心概念:
- 类型参数化:在类、接口、方法中使用类型参数
- 类型擦除:编译时泛型信息被擦除,转换为Object或边界类型
- 通配符:
?表示未知类型,? extends T上界通配符,? super T下界通配符
实战示例:
import java.util.*;
// 泛型类
class Box<T> {
private T content;
public Box(T content) {
this.content = content;
}
public T getContent() {
return content;
}
public void setContent(T content) {
this.content = content;
}
}
// 泛型方法
class GenericMethods {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
public static <T extends Number> double sum(T[] array) {
double sum = 0;
for (T element : array) {
sum += element.doubleValue();
}
return sum;
}
}
// 通配符使用
class WildcardDemo {
public static void printList(List<?> list) {
for (Object elem : list) {
System.out.print(elem + " ");
}
System.out.println();
}
public static void addNumbers(List<? super Integer> list) {
list.add(1);
list.add(2);
}
public static void processNumbers(List<? extends Number> list) {
for (Number num : list) {
System.out.print(num + " ");
}
System.out.println();
}
}
public class GenericsDemo {
public static void main(String[] args) {
// 泛型类使用
Box<String> stringBox = new Box<>("Hello");
Box<Integer> intBox = new Box<>(123);
System.out.println("字符串盒子: " + stringBox.getContent());
System.out.println("整数盒子: " + intBox.getContent());
// 泛型方法使用
String[] strArray = {"A", "B", "C"};
Integer[] intArray = {1, 2, 3, 4, 5};
GenericMethods.printArray(strArray);
GenericMethods.printArray(intArray);
System.out.println("整数数组求和: " + GenericMethods.sum(intArray));
// 通配符使用
List<String> stringList = new ArrayList<>();
stringList.add("Java");
stringList.add("Python");
List<Integer> intList = new ArrayList<>();
intList.add(10);
intList.add(20);
WildcardDemo.printList(stringList);
WildcardDemo.printList(intList);
List<Object> objectList = new ArrayList<>();
WildcardDemo.addNumbers(objectList);
System.out.println("添加数字后的对象列表: " + objectList);
WildcardDemo.processNumbers(intList);
}
}
2.2 反射(Reflection)
反射机制允许程序在运行时动态获取类的信息并操作类的成员。
核心API:
Class类:获取类的元数据Constructor:获取构造方法Field:获取和操作字段Method:获取和调用方法
实战示例:
import java.lang.reflect.*;
public class ReflectionDemo {
// 定义一个用于反射的类
static class Person {
private String name;
private int age;
public Person() {
this.name = "Unknown";
this.age = 0;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("Hello, I'm " + name);
}
private void privateMethod() {
System.out.println("这是一个私有方法");
}
}
public static void main(String[] args) throws Exception {
// 获取Class对象
Class<?> personClass = Person.class;
// 获取构造方法
Constructor<?>[] constructors = personClass.getConstructors();
System.out.println("公共构造方法:");
for (Constructor<?> constructor : constructors) {
System.out.println(" " + constructor);
}
// 使用反射创建对象
Constructor<?> constructor = personClass.getConstructor(String.class, int.class);
Person person = (Person) constructor.newInstance("Alice", 25);
System.out.println("创建的对象: " + person.getName());
// 获取字段
Field[] fields = personClass.getDeclaredFields();
System.out.println("所有字段:");
for (Field field : fields) {
System.out.println(" " + field.getName() + " (" + field.getType() + ")");
}
// 访问私有字段
Field nameField = personClass.getDeclaredField("name");
nameField.setAccessible(true); // 允许访问私有字段
nameField.set(person, "Bob");
System.out.println("修改后的名字: " + person.getName());
// 获取方法
Method[] methods = personClass.getDeclaredMethods();
System.out.println("所有方法:");
for (Method method : methods) {
System.out.println(" " + method.getName());
}
// 调用方法
Method sayHelloMethod = personClass.getMethod("sayHello");
sayHelloMethod.invoke(person);
// 调用私有方法
Method privateMethod = personClass.getDeclaredMethod("privateMethod");
privateMethod.setAccessible(true);
privateMethod.invoke(person);
}
}
2.3 注解(Annotations)
注解是Java 5引入的元数据机制,用于提供额外的信息给编译器、工具或运行时。
常用内置注解:
@Override:标记方法重写@Deprecated:标记已过时的方法/类@SuppressWarnings:抑制编译警告@FunctionalInterface:标记函数式接口
自定义注解示例:
import java.lang.annotation.*;
import java.lang.reflect.Method;
// 定义自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MyAnnotation {
String value() default "default";
int priority() default 1;
}
// 使用注解的类
class AnnotatedClass {
@MyAnnotation(value = "测试方法", priority = 2)
public void annotatedMethod() {
System.out.println("执行带注解的方法");
}
@MyAnnotation("另一个方法")
public void anotherMethod() {
System.out.println("执行另一个带注解的方法");
}
public void normalMethod() {
System.out.println("普通方法");
}
}
public class AnnotationDemo {
public static void main(String[] args) throws Exception {
AnnotatedClass obj = new AnnotatedClass();
Class<?> clazz = obj.getClass();
// 获取所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
// 检查方法是否有MyAnnotation注解
if (method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
System.out.println("方法: " + method.getName());
System.out.println(" 注解值: " + annotation.value());
System.out.println(" 优先级: " + annotation.priority());
// 调用带注解的方法
method.invoke(obj);
System.out.println();
}
}
}
}
第三部分:Java并发编程
3.1 线程基础与创建方式
Java提供了多种创建线程的方式,理解每种方式的适用场景很重要。
创建线程的三种方式:
- 继承
Thread类 - 实现
Runnable接口 - 实现
Callable接口(带返回值)
实战示例:
import java.util.concurrent.*;
// 方式1:继承Thread类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程 " + Thread.currentThread().getId() + " 正在运行");
}
}
// 方式2:实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable线程 " + Thread.currentThread().getId() + " 正在运行");
}
}
// 方式3:实现Callable接口(带返回值)
class MyCallable implements Callable<String> {
private int taskNumber;
public MyCallable(int taskNumber) {
this.taskNumber = taskNumber;
}
@Override
public String call() throws Exception {
System.out.println("任务 " + taskNumber + " 开始执行");
Thread.sleep(1000);
return "任务 " + taskNumber + " 完成,结果: " + (taskNumber * 2);
}
}
public class ThreadCreationDemo {
public static void main(String[] args) throws Exception {
// 方式1:继承Thread
MyThread thread1 = new MyThread();
thread1.start();
// 方式2:实现Runnable
Thread thread2 = new Thread(new MyRunnable());
thread2.start();
// 方式3:实现Callable
ExecutorService executor = Executors.newFixedThreadPool(3);
Future<String> future = executor.submit(new MyCallable(1));
// 获取结果(会阻塞直到任务完成)
String result = future.get();
System.out.println("Callable结果: " + result);
// 关闭线程池
executor.shutdown();
}
}
3.2 线程同步与锁机制
多线程环境下,共享资源的访问需要同步机制来保证数据一致性。
核心概念:
- synchronized:内置锁,可修饰方法或代码块
- Lock接口:更灵活的锁机制,如ReentrantLock
- volatile:保证变量的可见性
- 原子类:AtomicInteger等,提供原子操作
实战示例:
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
public class SynchronizationDemo {
// 使用synchronized的计数器
static class SynchronizedCounter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
// 使用ReentrantLock的计数器
static class LockCounter {
private int count = 0;
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
// 使用原子类的计数器
static class AtomicCounter {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
public static void main(String[] args) throws InterruptedException {
// 测试synchronized计数器
SynchronizedCounter syncCounter = new SynchronizedCounter();
testCounter(syncCounter, "synchronized");
// 测试Lock计数器
LockCounter lockCounter = new LockCounter();
testCounter(lockCounter, "ReentrantLock");
// 测试原子计数器
AtomicCounter atomicCounter = new AtomicCounter();
testCounter(atomicCounter, "AtomicInteger");
}
static void testCounter(Object counter, String type) throws InterruptedException {
final int threadCount = 10;
final int incrementsPerThread = 1000;
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < incrementsPerThread; j++) {
if (counter instanceof SynchronizedCounter) {
((SynchronizedCounter) counter).increment();
} else if (counter instanceof LockCounter) {
((LockCounter) counter).increment();
} else if (counter instanceof AtomicCounter) {
((AtomicCounter) counter).increment();
}
}
});
threads[i].start();
}
for (Thread thread : threads) {
thread.join();
}
int finalCount = 0;
if (counter instanceof SynchronizedCounter) {
finalCount = ((SynchronizedCounter) counter).getCount();
} else if (counter instanceof LockCounter) {
finalCount = ((LockCounter) counter).getCount();
} else if (counter instanceof AtomicCounter) {
finalCount = ((AtomicCounter) counter).getCount();
}
System.out.println(type + " 计数器最终值: " + finalCount +
" (期望值: " + (threadCount * incrementsPerThread) + ")");
}
}
3.3 并发工具类
Java并发包(java.util.concurrent)提供了丰富的并发工具类。
常用工具类:
- ExecutorService:线程池管理
- Future/Callable:异步任务和结果获取
- CountDownLatch:等待多个线程完成
- CyclicBarrier:线程间同步点
- Semaphore:控制并发数量
- ConcurrentHashMap:线程安全的Map
实战示例:
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ConcurrencyToolsDemo {
public static void main(String[] args) throws Exception {
// 1. 线程池使用
ExecutorService executor = Executors.newFixedThreadPool(5);
// 提交多个任务
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("任务 " + taskId + " 在线程 " +
Thread.currentThread().getName() + " 中执行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// 2. CountDownLatch示例
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
System.out.println("线程 " + Thread.currentThread().getId() + " 准备就绪");
Thread.sleep(1000);
System.out.println("线程 " + Thread.currentThread().getId() + " 完成任务");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
latch.countDown();
}
}).start();
}
System.out.println("主线程等待所有子线程完成...");
latch.await(); // 等待所有线程完成
System.out.println("所有子线程已完成!");
// 3. CyclicBarrier示例
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("所有线程到达屏障点,继续执行");
});
for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
System.out.println("线程 " + Thread.currentThread().getId() + " 到达屏障");
barrier.await(); // 等待其他线程
System.out.println("线程 " + Thread.currentThread().getId() + " 继续执行");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
// 4. Semaphore示例(控制并发数)
Semaphore semaphore = new Semaphore(2); // 允许2个线程同时访问
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
semaphore.acquire(); // 获取许可
System.out.println("线程 " + Thread.currentThread().getId() + " 获得许可,开始执行");
Thread.sleep(2000);
System.out.println("线程 " + Thread.currentThread().getId() + " 执行完成,释放许可");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release();
}
}).start();
}
// 5. ConcurrentHashMap示例
ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
// 多个线程同时操作
ExecutorService mapExecutor = Executors.newFixedThreadPool(10);
AtomicInteger counter = new AtomicInteger(0);
for (int i = 0; i < 100; i++) {
mapExecutor.submit(() -> {
String key = "key-" + counter.incrementAndGet();
concurrentMap.put(key, Thread.currentThread().getId());
});
}
mapExecutor.shutdown();
mapExecutor.awaitTermination(1, TimeUnit.SECONDS);
System.out.println("ConcurrentHashMap大小: " + concurrentMap.size());
// 关闭线程池
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
}
}
第四部分:JVM与性能优化
4.1 JVM内存模型
理解JVM内存结构是进行性能调优的基础。
JVM内存区域:
- 堆(Heap):对象实例存储区域,分为新生代和老年代
- 方法区(Method Area):存储类信息、常量、静态变量等(JDK 8后称为元空间)
- 虚拟机栈(VM Stack):存储局部变量、方法调用等
- 本地方法栈(Native Method Stack):为Native方法服务
- 程序计数器(Program Counter Register):记录当前线程执行的字节码指令地址
实战示例:
// 演示JVM内存使用
public class JVMMemoryDemo {
// 静态变量存储在方法区(元空间)
private static String staticString = "静态字符串";
// 实例变量存储在堆中
private String instanceString = "实例字符串";
// 局部变量存储在栈中
public void method() {
String localVar = "局部变量";
System.out.println(localVar);
}
// 大对象演示(可能直接进入老年代)
public void createLargeObject() {
// 创建一个大数组,可能直接进入老年代
byte[] largeArray = new byte[10 * 1024 * 1024]; // 10MB
System.out.println("创建了10MB的大数组");
}
// 内存泄漏演示
static class MemoryLeak {
private static List<byte[]> leakList = new ArrayList<>();
public static void addData() {
// 每次调用添加1MB数据,但不释放,导致内存泄漏
byte[] data = new byte[1024 * 1024];
leakList.add(data);
System.out.println("添加了1MB数据,当前列表大小: " + leakList.size() + "MB");
}
}
public static void main(String[] args) {
JVMMemoryDemo demo = new JVMMemoryDemo();
demo.method();
// 演示大对象
demo.createLargeObject();
// 演示内存泄漏(注意:实际运行时需要调整JVM参数)
// MemoryLeak.addData();
// MemoryLeak.addData();
}
}
4.2 垃圾回收机制(GC)
Java的垃圾回收机制自动管理内存,但理解GC原理对性能调优至关重要。
GC核心概念:
- 标记-清除:先标记存活对象,再清除未标记对象
- 复制算法:将内存分为两块,每次只使用一块,复制存活对象到另一块
- 标记-整理:标记存活对象,然后将存活对象向一端移动,清理另一端
- 分代收集:新生代使用复制算法,老年代使用标记-整理算法
GC调优实战:
// JVM参数示例(在运行时添加)
// -Xms512m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45
public class GCDemo {
// 创建大量对象,触发GC
public static void createObjects() {
List<Object> list = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
list.add(new byte[1024]); // 每个对象1KB
if (i % 10000 == 0) {
System.out.println("已创建 " + i + " 个对象");
}
}
// 清空列表,使对象可被回收
list.clear();
}
// 强引用、软引用、弱引用、虚引用示例
public static void referenceDemo() {
// 强引用
Object strongRef = new Object();
// 软引用(内存不足时回收)
SoftReference<Object> softRef = new SoftReference<>(new Object());
// 弱引用(下次GC时回收)
WeakReference<Object> weakRef = new WeakReference<>(new Object());
// 虚引用(用于对象回收跟踪)
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), null);
System.out.println("强引用对象: " + strongRef);
System.out.println("软引用对象: " + softRef.get());
System.out.println("弱引用对象: " + weakRef.get());
System.out.println("虚引用对象: " + phantomRef.get());
}
public static void main(String[] args) {
// referenceDemo();
// 创建对象触发GC
for (int i = 0; i < 5; i++) {
System.out.println("第 " + (i + 1) + " 轮创建对象");
createObjects();
System.gc(); // 建议JVM进行GC(不保证立即执行)
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
4.3 性能监控与调优工具
常用工具:
- jvisualvm:JDK自带的可视化监控工具
- jconsole:JDK自带的监控工具
- jstat:监控JVM统计信息
- jmap:生成堆转储文件
- jstack:生成线程转储文件
- Arthas:阿里开源的诊断工具
实战示例:
// 模拟性能问题代码
public class PerformanceDemo {
// 模拟CPU密集型任务
public static void cpuIntensiveTask() {
long startTime = System.currentTimeMillis();
long result = 0;
for (long i = 0; i < 1000000000L; i++) {
result += i;
}
long endTime = System.currentTimeMillis();
System.out.println("CPU密集型任务耗时: " + (endTime - startTime) + "ms, 结果: " + result);
}
// 模拟内存密集型任务
public static void memoryIntensiveTask() {
List<byte[]> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
list.add(new byte[1024 * 1024]); // 每个1MB
}
System.out.println("内存密集型任务完成,分配了1GB内存");
}
// 模拟I/O密集型任务
public static void ioIntensiveTask() throws Exception {
File file = new File("test_large.txt");
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
for (int i = 0; i < 1000000; i++) {
writer.write("Line " + i + ": This is a test line for I/O operations.\n");
}
}
System.out.println("I/O密集型任务完成");
}
public static void main(String[] args) throws Exception {
// 运行不同类型的性能任务
cpuIntensiveTask();
memoryIntensiveTask();
ioIntensiveTask();
// 模拟线程死锁
simulateDeadlock();
}
// 模拟死锁
private static void simulateDeadlock() {
Object lock1 = new Object();
Object lock2 = new Object();
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("线程1获取lock1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("线程1获取lock2");
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("线程2获取lock2");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1) {
System.out.println("线程2获取lock1");
}
}
});
thread1.start();
thread2.start();
}
}
第五部分:Java高级框架与生态
5.1 Spring框架核心
Spring是Java企业级开发的事实标准,掌握Spring是高级Java开发者的必备技能。
核心概念:
- IoC(控制反转):将对象的创建和管理交给Spring容器
- DI(依赖注入):通过构造器、setter或字段注入依赖
- AOP(面向切面编程):在不修改源代码的情况下添加额外功能
- Spring Boot:简化Spring应用的配置和部署
实战示例:
// Spring Boot应用示例
// 1. 主应用类
@SpringBootApplication
public class SpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class, args);
}
}
// 2. 实体类
@Entity
@Table(name = "users")
class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
// 构造函数、getter、setter省略
}
// 3. Repository接口
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
List<User> findByName(String name);
}
// 4. Service层
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User createUser(User user) {
return userRepository.save(user);
}
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
}
// 5. Controller层
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User createdUser = userService.createUser(user);
return ResponseEntity.ok(createdUser);
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
if (user != null) {
return ResponseEntity.ok(user);
} else {
return ResponseEntity.notFound().build();
}
}
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
return ResponseEntity.ok(userService.getAllUsers());
}
}
// 6. 配置类
@Configuration
public class AppConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
5.2 MyBatis与数据库操作
MyBatis是优秀的持久层框架,提供灵活的SQL映射。
核心概念:
- SqlSessionFactory:创建SqlSession的工厂
- SqlSession:执行SQL操作的核心接口
- Mapper接口:定义数据库操作方法
- XML映射文件:SQL语句和结果映射
实战示例:
<!-- UserMapper.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<!-- 结果映射 -->
<resultMap id="UserResultMap" type="com.example.entity.User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="email" column="email"/>
<result property="createTime" column="create_time"/>
</resultMap>
<!-- 查询所有用户 -->
<select id="selectAll" resultMap="UserResultMap">
SELECT * FROM users
</select>
<!-- 根据ID查询用户 -->
<select id="selectById" parameterType="Long" resultMap="UserResultMap">
SELECT * FROM users WHERE id = #{id}
</select>
<!-- 根据邮箱查询用户 -->
<select id="selectByEmail" parameterType="String" resultMap="UserResultMap">
SELECT * FROM users WHERE email = #{email}
</select>
<!-- 插入用户 -->
<insert id="insert" parameterType="com.example.entity.User">
INSERT INTO users (name, email, create_time)
VALUES (#{name}, #{email}, #{createTime})
<selectKey keyProperty="id" order="AFTER" resultType="Long">
SELECT LAST_INSERT_ID()
</selectKey>
</insert>
<!-- 更新用户 -->
<update id="update" parameterType="com.example.entity.User">
UPDATE users
<set>
<if test="name != null">name = #{name},</if>
<if test="email != null">email = #{email},</if>
</set>
WHERE id = #{id}
</update>
<!-- 删除用户 -->
<delete id="delete" parameterType="Long">
DELETE FROM users WHERE id = #{id}
</delete>
<!-- 动态SQL示例:条件查询 -->
<select id="selectByCondition" parameterType="Map" resultMap="UserResultMap">
SELECT * FROM users
<where>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="email != null and email != ''">
AND email LIKE CONCAT('%', #{email}, '%')
</if>
<if test="startTime != null">
AND create_time >= #{startTime}
</if>
<if test="endTime != null">
AND create_time <= #{endTime}
</if>
</where>
</select>
</mapper>
// Java代码示例
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyBatisDemo {
public static void main(String[] args) throws Exception {
// 1. 加载MyBatis配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 2. 创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 3. 获取SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
// 4. 获取Mapper接口
UserMapper userMapper = session.getMapper(UserMapper.class);
// 5. 执行数据库操作
// 查询所有用户
List<User> users = userMapper.selectAll();
System.out.println("查询到 " + users.size() + " 个用户");
// 根据ID查询用户
User user = userMapper.selectById(1L);
System.out.println("ID为1的用户: " + user);
// 插入新用户
User newUser = new User();
newUser.setName("张三");
newUser.setEmail("zhangsan@example.com");
newUser.setCreateTime(new Date());
userMapper.insert(newUser);
System.out.println("新用户ID: " + newUser.getId());
// 动态SQL查询
Map<String, Object> condition = new HashMap<>();
condition.put("name", "张");
condition.put("startTime", "2023-01-01");
List<User> filteredUsers = userMapper.selectByCondition(condition);
System.out.println("条件查询结果: " + filteredUsers.size() + " 个用户");
// 提交事务
session.commit();
}
}
}
5.3 分布式系统基础
现代Java应用通常部署在分布式环境中,理解分布式系统基础是高级开发者的必备技能。
核心概念:
- CAP定理:一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)
- 分布式锁:解决分布式环境下的资源竞争问题
- 分布式事务:保证跨多个服务的数据一致性
- 服务发现与注册:如Eureka、Consul、Nacos
实战示例:
// 分布式锁示例(基于Redis)
public class RedisDistributedLock {
private static final String LOCK_KEY = "distributed_lock";
private static final long LOCK_EXPIRE_TIME = 30000; // 30秒
// 使用Redisson客户端实现分布式锁
public static void main(String[] args) {
// 配置Redisson客户端
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
// 获取分布式锁
RLock lock = redisson.getLock(LOCK_KEY);
try {
// 尝试获取锁,最多等待10秒,锁自动释放时间30秒
boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);
if (isLocked) {
System.out.println("获取分布式锁成功,线程: " + Thread.currentThread().getName());
// 执行关键业务逻辑
System.out.println("执行业务操作...");
Thread.sleep(5000);
System.out.println("业务操作完成");
} else {
System.out.println("获取分布式锁失败");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
System.out.println("释放分布式锁");
}
}
redisson.shutdown();
}
}
// 分布式事务示例(Seata)
// 1. 服务A(订单服务)
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private AccountService accountService;
@Autowired
private StorageService storageService;
@GlobalTransactional(name = "createOrder", rollbackFor = Exception.class)
public void createOrder(Order order) {
// 1. 创建订单
orderMapper.insert(order);
// 2. 扣减账户余额
accountService.decrease(order.getUserId(), order.getAmount());
// 3. 扣减库存
storageService.decrease(order.getProductId(), order.getQuantity());
System.out.println("订单创建成功: " + order.getId());
}
}
// 2. 服务B(账户服务)
@Service
public class AccountService {
@Autowired
private AccountMapper accountMapper;
@Transactional(rollbackFor = Exception.class)
public void decrease(Long userId, BigDecimal amount) {
// 扣减账户余额
accountMapper.decrease(userId, amount);
System.out.println("账户扣减成功: userId=" + userId + ", amount=" + amount);
}
}
// 3. 服务C(库存服务)
@Service
public class StorageService {
@Autowired
private StorageMapper storageMapper;
@Transactional(rollbackFor = Exception.class)
public void decrease(Long productId, Integer quantity) {
// 扣减库存
storageMapper.decrease(productId, quantity);
System.out.println("库存扣减成功: productId=" + productId + ", quantity=" + quantity);
}
}
第六部分:实战项目与最佳实践
6.1 项目架构设计
分层架构示例:
├── controller/ # 控制层,处理HTTP请求
├── service/ # 业务逻辑层
├── repository/ # 数据访问层
├── entity/ # 实体类
├── dto/ # 数据传输对象
├── config/ # 配置类
├── exception/ # 异常处理
└── util/ # 工具类
6.2 代码规范与设计模式
常用设计模式:
- 单例模式:确保一个类只有一个实例
- 工厂模式:创建对象而不指定具体类
- 观察者模式:定义对象间的一对多依赖关系
- 策略模式:定义一系列算法,封装每个算法
- 装饰器模式:动态添加对象功能
实战示例:
// 策略模式示例:支付方式
interface PaymentStrategy {
void pay(double amount);
}
class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
public CreditCardPayment(String cardNumber) {
this.cardNumber = cardNumber;
}
@Override
public void pay(double amount) {
System.out.println("使用信用卡支付: " + amount + "元,卡号: " + cardNumber);
}
}
class AlipayPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用支付宝支付: " + amount + "元");
}
}
class WechatPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用微信支付: " + amount + "元");
}
}
class PaymentContext {
private PaymentStrategy strategy;
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void executePayment(double amount) {
if (strategy != null) {
strategy.pay(amount);
} else {
System.out.println("未设置支付策略");
}
}
}
// 观察者模式示例:消息通知
interface Observer {
void update(String message);
}
class EmailObserver implements Observer {
private String email;
public EmailObserver(String email) {
this.email = email;
}
@Override
public void update(String message) {
System.out.println("发送邮件到 " + email + ": " + message);
}
}
class SmsObserver implements Observer {
private String phone;
public SmsObserver(String phone) {
this.phone = phone;
}
@Override
public void update(String message) {
System.out.println("发送短信到 " + phone + ": " + message);
}
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
public class DesignPatternDemo {
public static void main(String[] args) {
// 策略模式演示
PaymentContext context = new PaymentContext();
context.setStrategy(new CreditCardPayment("1234-5678-9012-3456"));
context.executePayment(100.0);
context.setStrategy(new AlipayPayment());
context.executePayment(200.0);
context.setStrategy(new WechatPayment());
context.executePayment(300.0);
System.out.println("\n" + "=".repeat(50) + "\n");
// 观察者模式演示
Subject subject = new Subject();
Observer emailObserver = new EmailObserver("user@example.com");
Observer smsObserver = new SmsObserver("13800138000");
subject.addObserver(emailObserver);
subject.addObserver(smsObserver);
subject.notifyObservers("系统维护通知:今晚10点系统将进行维护");
}
}
6.3 单元测试与集成测试
测试框架:
- JUnit 5:单元测试框架
- Mockito:Mock框架,用于模拟依赖
- Spring Test:Spring集成测试
- Testcontainers:用于集成测试的容器化工具
实战示例:
// 单元测试示例
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class Calculator {
public int add(int a, int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
}
class CalculatorTest {
private Calculator calculator;
@BeforeEach
void setUp() {
calculator = new Calculator();
}
@Test
@DisplayName("测试加法运算")
void testAdd() {
assertEquals(5, calculator.add(2, 3));
assertEquals(0, calculator.add(-1, 1));
assertEquals(10, calculator.add(5, 5));
}
@Test
@DisplayName("测试减法运算")
void testSubtract() {
assertEquals(1, calculator.subtract(3, 2));
assertEquals(-2, calculator.subtract(1, 3));
assertEquals(0, calculator.subtract(5, 5));
}
@Test
@DisplayName("测试边界情况")
void testBoundaryCases() {
// 测试最大值
assertEquals(Integer.MAX_VALUE, calculator.add(Integer.MAX_VALUE, 0));
// 测试最小值
assertEquals(Integer.MIN_VALUE, calculator.add(Integer.MIN_VALUE, 0));
}
}
// Mockito示例
import org.junit.jupiter.api.Test;
import org.mockito.*;
class UserService {
private UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User getUserById(Long id) {
return userRepository.findById(id);
}
public User createUser(User user) {
return userRepository.save(user);
}
}
interface UserRepository {
User findById(Long id);
User save(User user);
}
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
void testGetUserById() {
// 准备测试数据
User mockUser = new User();
mockUser.setId(1L);
mockUser.setName("Test User");
// 模拟行为
when(userRepository.findById(1L)).thenReturn(mockUser);
// 执行测试
User result = userService.getUserById(1L);
// 验证结果
assertNotNull(result);
assertEquals(1L, result.getId());
assertEquals("Test User", result.getName());
// 验证方法调用
verify(userRepository, times(1)).findById(1L);
}
@Test
void testCreateUser() {
User userToCreate = new User();
userToCreate.setName("New User");
User savedUser = new User();
savedUser.setId(100L);
savedUser.setName("New User");
when(userRepository.save(userToCreate)).thenReturn(savedUser);
User result = userService.createUser(userToCreate);
assertNotNull(result);
assertEquals(100L, result.getId());
assertEquals("New User", result.getName());
verify(userRepository, times(1)).save(userToCreate);
}
}
第七部分:持续学习与资源推荐
7.1 学习路径建议
基础阶段(1-2个月):
- Java核心语法、OOP、集合框架、异常处理
- 完成5-10个小型控制台项目
进阶阶段(2-3个月):
- 泛型、反射、注解、并发编程
- 学习Spring Boot基础
- 完成1-2个Web应用项目
高级阶段(3-6个月):
- JVM原理与性能调优
- 分布式系统基础
- 微服务架构
- 完成1个完整的分布式系统项目
专家阶段(持续学习):
- 深入研究特定领域(如大数据、AI、区块链)
- 参与开源项目
- 撰写技术博客和文章
7.2 推荐资源
书籍推荐:
- 《Java核心技术》(Core Java)
- 《Effective Java》
- 《Java并发编程实战》
- 《深入理解Java虚拟机》
- 《Spring实战》
- 《微服务架构设计模式》
在线课程:
- Coursera: “Java Programming and Software Engineering Fundamentals”
- Udemy: “Java Programming Masterclass”
- 极客时间: “Java核心技术36讲”
- 慕课网: “Java高级开发实战”
开源项目:
- Spring Framework
- Apache Commons
- Guava
- Netty
- Elasticsearch
技术社区:
- Stack Overflow
- GitHub
- CSDN
- 掘金
- 知乎
7.3 实践建议
- 每日编码:坚持每天写代码,哪怕只有30分钟
- 代码审查:学习阅读和审查他人代码
- 参与开源:从修复小bug开始参与开源项目
- 技术分享:定期整理学习笔记并分享
- 解决问题:主动解决实际问题,而不仅仅是学习理论
结语
Java高级学习是一个循序渐进的过程,需要理论与实践相结合。通过本指南提供的系统学习路径和实战示例,你可以逐步掌握Java的核心概念与高级技巧。记住,编程是一门实践的艺术,只有通过不断的编码、调试和优化,才能真正成为Java专家。保持好奇心,持续学习,勇于实践,你一定能在Java开发的道路上越走越远。
