Java中的异常,枚举,泛型,代理
一、Java 异常(Exception)
异常是程序运行时出现的意外情况,Java 通过异常处理机制增强程序的健壮性。
1. 异常体系结构
- 顶层父类:
Throwable
- Error:严重错误(如
OutOfMemoryError
),程序无法处理,通常无需捕获 - Exception:可处理的异常
- 受检异常(Checked Exception):编译期检查,必须处理(如
IOException
) - 非受检异常(Unchecked Exception):运行时异常,可选择性处理(如
NullPointerException
)
- 受检异常(Checked Exception):编译期检查,必须处理(如
- Error:严重错误(如
2. 异常处理关键字
try
:包裹可能发生异常的代码块catch
:捕获并处理指定类型的异常finally
:无论是否发生异常,都会执行的代码块(常用于资源释放)throw
:手动抛出异常throws
:声明方法可能抛出的异常
3. 示例代码
java
运行
public class ExceptionDemo {public static void main(String[] args) {try {int result = divide(10, 0);System.out.println(result);} catch (ArithmeticException e) {System.out.println("捕获异常:" + e.getMessage());} finally {System.out.println("无论是否异常都会执行");}}public static int divide(int a, int b) throws ArithmeticException {if (b == 0) {throw new ArithmeticException("除数不能为0");}return a / b;}
}
4. 自定义异常
通过继承Exception
(受检)或RuntimeException
(非受检)实现:
java
运行
class CustomException extends RuntimeException {public CustomException(String message) {super(message);}
}
二、Java 枚举(Enum)
枚举是一种特殊的类,用于定义固定数量的常量集合(如季节、星期等)。
1. 基本特性
- 枚举类默认继承
java.lang.Enum
,不能继承其他类 - 枚举常量是枚举类的实例,默认被
public static final
修饰 - 枚举类可以有构造器、方法和属性,但构造器必须是私有(
private
)的
2. 基本用法
java
运行
// 简单枚举
enum Season {SPRING, SUMMER, AUTUMN, WINTER
}// 带属性和方法的枚举
enum Weekday {MONDAY("周一", 1),TUESDAY("周二", 2);private final String chineseName;private final int index;// 私有构造器Weekday(String chineseName, int index) {this.chineseName = chineseName;this.index = index;}// 自定义方法public String getChineseName() {return chineseName;}
}
3. 常用方法
values()
:返回枚举常量数组valueOf(String name)
:根据名称获取枚举常量ordinal()
:返回枚举常量的序号(从 0 开始)
4. 应用场景
- 状态标识(如订单状态:待支付、已支付、已取消)
- 有限选项(如性别:男、女)
- 替代常量定义(比
public static final
更安全)
三、Java 泛型(Generics)
泛型允许在定义类、接口和方法时使用类型参数,实现代码复用和类型安全。
1. 核心作用
- 类型安全:编译期检查类型,避免运行时
ClassCastException
- 代码复用:同一套逻辑支持多种数据类型
- 消除强制类型转换:提高代码可读性
2. 基本用法
泛型类:
java
运行
class Box<T> { // T为类型参数private T value;public void setValue(T value) {this.value = value;}public T getValue() {return value;}
}// 使用
Box<String> stringBox = new Box<>();
stringBox.setValue("Hello");
String str = stringBox.getValue(); // 无需强制转换
泛型方法:
java
运行
public class GenericMethod {// 泛型方法,E为类型参数public static <E> void printArray(E[] array) {for (E element : array) {System.out.print(element + " ");}}public static void main(String[] args) {Integer[] intArray = {1, 2, 3};String[] strArray = {"a", "b", "c"};printArray(intArray); // 自动推断类型printArray(strArray);}
}
泛型接口:
java
运行
interface Generator<T> {T generate();
}class NumberGenerator implements Generator<Integer> {@Overridepublic Integer generate() {return (int)(Math.random() * 100);}
}
3. 通配符
<?>
:无界通配符,表示任意类型<? extends T>
:上界通配符,表示 T 及其子类<? super T>
:下界通配符,表示 T 及其父类
java
运行
// 只能读取,不能添加(除null外)
public void printList(List<? extends Number> list) {for (Number n : list) {System.out.println(n);}
}// 只能添加T及其子类,读取时只能当作Object
public void addNumbers(List<? super Integer> list) {list.add(1);list.add(2);
}
4. 类型擦除
Java 泛型采用编译期类型擦除机制,运行时不保留泛型类型信息,会被替换为原始类型(如T
被替换为Object
)。
四、Java 代理(Proxy)
代理模式是一种设计模式,通过代理对象控制对目标对象的访问,Java 提供动态代理机制。
1. 代理类型
- 静态代理:编译期生成代理类,手动编写代理逻辑
- 动态代理:运行时动态生成代理类,无需手动编写
2. 静态代理示例
java
运行
// 接口
interface UserService {void save();
}// 目标类
class UserServiceImpl implements UserService {@Overridepublic void save() {System.out.println("执行保存操作");}
}// 代理类
class UserServiceProxy implements UserService {private UserService target;public UserServiceProxy(UserService target) {this.target = target;}@Overridepublic void save() {System.out.println("前置处理:开启事务");target.save(); // 调用目标方法System.out.println("后置处理:提交事务");}
}// 使用
public class StaticProxyDemo {public static void main(String[] args) {UserService target = new UserServiceImpl();UserService proxy = new UserServiceProxy(target);proxy.save(); // 通过代理调用}
}
3. 动态代理(JDK 代理)
基于接口实现,通过java.lang.reflect.Proxy
和InvocationHandler
实现:
java
运行
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// InvocationHandler实现类
class LogHandler implements InvocationHandler {private Object target; // 目标对象public LogHandler(Object target) {this.target = target;}// 代理逻辑@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("日志:调用方法前");Object result = method.invoke(target, args); // 调用目标方法System.out.println("日志:调用方法后");return result;}
}// 使用动态代理
public class DynamicProxyDemo {public static void main(String[] args) {UserService target = new UserServiceImpl();// 创建代理对象UserService proxy = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(), // 类加载器target.getClass().getInterfaces(), // 实现的接口new LogHandler(target) // 代理逻辑处理器);proxy.save(); // 通过代理调用}
}
4. 应用场景
- AOP(面向切面编程):如日志、事务、权限控制
- 远程调用:如 RPC 框架通过代理实现网络通信
- 延迟加载:代理对象在真正需要时才初始化目标对象
5. CGLIB 代理
JDK 代理要求目标类实现接口,CGLIB(Code Generation Library)通过继承目标类生成代理类,可代理无接口的类(需引入第三方库)。
总结:异常处理保障程序稳定性,枚举增强常量定义的安全性,泛型实现类型安全的代码复用,代理模式实现对目标对象的增强和控制,这些特性共同构成了 Java 语言的强大功能。