在上一期中,我们探讨了 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();
    }
}









