在上一期中,我们探讨了 Java 的基础语法、面向对象核心特性、集合框架及异常处理。本期将深入 Java 高级特性,这些内容是从初级开发者迈向中高级的关键,也是企业级开发中的高频应用点。
一、泛型:类型安全的 "保护伞"
1. 泛型的基本使用
(1)泛型类
// 定义泛型类:存储任意类型的对象
public class Box<T> {
private T content;
public void setContent(T content) {
this.content = content;
}
public T getContent() {
return content;
}
public static void main(String[] args) {
// 使用时指定类型(String)
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello Generics");
String str = stringBox.getContent(); // 无需强制转换
// 编译期检查:不能放入其他类型
// stringBox.setContent(123); // 编译报错
}
}
(2)泛型方法
public class GenericMethodDemo {
// 泛型方法:交换数组中两个元素的位置
public static <T> void swap(T[] array, int i, int j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3, 4};
swap(intArray, 0, 3); // 交换整数数组
String[] strArray = {"A", "B", "C"};
swap(strArray, 1, 2); // 交换字符串数组
}
}
2. 泛型通配符:灵活的类型限制
<? extends T>
:上限通配符,只能接收T
及其子类(只读,不能添加元素,因不确定具体类型);<? super T>
:下限通配符,只能接收T
及其父类(可写,能添加T
及其子类元素)。
import java.util.ArrayList;
import java.util.List;
public class WildcardDemo {
// 打印所有Number及其子类(如Integer、Double)的集合
public static void printNumberList(List<? extends Number> list) {
for (Number num : list) {
System.out.println(num);
}
// list.add(100); // 编译报错:不能添加元素(不确定具体类型)
}
// 向集合中添加Integer及其子类(实际只有Integer,因Integer是final类)
public static void addIntegers(List<? super Integer> list) {
list.add(100); // 合法
list.add(200); // 合法
}
public static void main(String[] args) {
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
printNumberList(intList); // 合法:Integer是Number的子类
List<Object> objList = new ArrayList<>();
addIntegers(objList); // 合法:Object是Integer的父类
}
}
二、Lambda 表达式与函数式编程
1. Lambda 表达式:简化匿名内部类
import java.util.Arrays;
import java.util.List;
public class LambdaDemo {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 传统匿名内部类:遍历集合
names.forEach(new java.util.function.Consumer<String>() {
@Override
public void accept(String name) {
System.out.println(name);
}
});
// Lambda表达式简化:效果同上
names.forEach(name -> System.out.println(name));
// 更简洁的方法引用(::):当参数直接传递给方法时
names.forEach(System.out::println);
}
}
2. Stream API:集合操作的 "瑞士军刀"
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamDemo {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("Alice", 90, "Math"),
new Student("Bob", 85, "English"),
new Student("Charlie", 95, "Math"),
new Student("David", 75, "Math")
);
// 需求:找出数学(Math)成绩>=90分的学生姓名,按成绩降序排列
List<String> result = students.stream()
// 过滤:只保留Math学科且成绩>=90
.filter(s -> "Math".equals(s.getSubject()) && s.getScore() >= 90)
// 排序:按成绩降序
.sorted((s1, s2) -> Integer.compare(s2.getScore(), s1.getScore()))
// 映射:提取姓名
.map(Student::getName)
// 收集结果到List
.collect(Collectors.toList());
System.out.println(result); // 输出:[Charlie, Alice]
}
static class Student {
private String name;
private int score;
private String subject;
// 构造器、getter省略
public Student(String name, int score, String subject) {
this.name = name;
this.score = score;
this.subject = subject;
}
public String getName() { return name; }
public int getScore() { return score; }
public String getSubject() { return subject; }
}
}
三、并发编程:应对多线程场景
1. 线程的创建方式
(1)继承 Thread 类
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Thread: " + i);
try {
Thread.sleep(100); // 休眠100ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // 启动线程(调用run())
}
}
(2)实现 Runnable 接口(推荐,避免单继承限制)
public class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行逻辑
}
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}
(3)使用 Callable 和 Future(可获取返回值)
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum; // 返回计算结果
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> task = new FutureTask<>(new MyCallable());
new Thread(task).start();
// 获取线程返回值(会阻塞直到计算完成)
System.out.println("1-100的和:" + task.get());
}
}
2. 线程池:高效管理线程资源
FixedThreadPool
:固定大小的线程池;CachedThreadPool
:可缓存的线程池(线程数随需求变化);ScheduledThreadPool
:支持定时任务的线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo {
public static void main(String[] args) {
// 创建固定大小为5的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
// 提交10个任务
for (int i = 0; i < 10; i++) {
final int taskNum = i;
executor.submit(() -> {
System.out.println("执行任务 " + taskNum + ",线程:" + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
executor.shutdown(); // 关闭线程池
}
}
3. 线程安全:避免并发问题
- synchronized:关键字,修饰方法或代码块,保证同一时间只有一个线程执行;
- Lock:接口(如
ReentrantLock
),更灵活的锁机制(可中断、超时获取锁); - 原子类:
java.util.concurrent.atomic
包下的类(如AtomicInteger
),通过 CAS 机制实现无锁线程安全。
public class SynchronizedDemo {
private int count = 0;
// 同步方法:锁住当前对象
public synchronized void increment() {
count++;
}
public static void main(String[] args) throws InterruptedException {
SynchronizedDemo demo = new SynchronizedDemo();
// 1000个线程,每个线程执行1000次自增
for (int i = 0; i < 1000; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
demo.increment();
}
}).start();
}
Thread.sleep(2000); // 等待所有线程执行完毕
System.out.println("count = " + demo.count); // 输出1000000(线程安全)
}
}
四、实战案例:简易 REST 接口开发
1. 项目结构
src/main/java/com/example/demo/
├── DemoApplication.java // 启动类
├── controller/UserController.java // 接口层
├── service/UserService.java // 业务层
├── repository/UserRepository.java // 数据访问层
└── model/User.java // 实体类
2. 核心代码
(1)实体类User.java
package com.example.demo.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
// 构造器、getter、setter省略
}
(2)数据访问层UserRepository.java
package com.example.demo.repository;
import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
// 继承JpaRepository,自动获得CRUD方法
public interface UserRepository extends JpaRepository<User, Long> {
// 自定义查询:根据年龄查询用户
List<User> findByAgeGreaterThan(int age);
}
(3)业务层UserService.java
package com.example.demo.service;
import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 获取所有用户
public List<User> getAllUsers() {
return userRepository.findAll();
}
// 根据ID获取用户
public Optional<User> getUserById(Long id) {
return userRepository.findById(id);
}
// 创建用户
public User createUser(User user) {
return userRepository.save(user);
}
// 更新用户
public User updateUser(Long id, User userDetails) {
return userRepository.findById(id)
.map(user -> {
user.setName(userDetails.getName());
user.setAge(userDetails.getAge());
return userRepository.save(user);
})
.orElseThrow(() -> new RuntimeException("User not found"));
}
// 删除用户
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
(4)接口层UserController.java
package com.example.demo.controller;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// GET /api/users:获取所有用户
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
// GET /api/users/{id}:获取单个用户
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
return userService.getUserById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
// POST /api/users:创建用户
@PostMapping
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
// PUT /api/users/{id}:更新用户
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
try {
return ResponseEntity.ok(userService.updateUser(id, user));
} catch (RuntimeException e) {
return ResponseEntity.notFound().build();
}
}
// DELETE /api/users/{id}:删除用户
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}