Java异常处理是编程中的重要部分,下面我将分类讲解常见的异常类型,通过具体示例说明其产生原因,并提供相应的解决策略。
示例:
try {
Files.walk(Paths.get(".")).forEach(path -> {
// 访问无权限目录
});
} catch(DirectoryIteratorException e) {
// 目录迭代过程中出错
}
原因:目录遍历过程中发生IO错误
解决策略:
处理单个文件错误
跳过无权限目录
使用安全遍历方法
// 解决方案示例
try {
Files.walk(Paths.get(".")).forEach(path -> {
try {
// 处理文件
} catch(IOException e) {
logger.warn("跳过文件: " + path, e);
}
});
} catch(IOException e) {
logger.error("遍历失败", e);
}
示例
try {
Files.walk(Paths.get("."), FileVisitOption.FOLLOW_LINKS)
.forEach(path -> {
// 遇到符号链接循环
});
} catch(FileSystemLoopException e) {
// 检测到符号链接循环
}
原因:符号链接形成循环引用
解决策略:
限制遍历深度
检测循环链接
不使用FOLLOW_LINKS选项
// 解决方案示例
Files.walkFileTree(startPath, new SimpleFileVisitor() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if(/* 检测循环 */) {
return FileVisitResult.SKIP_SUBTREE;
}
return FileVisitResult.CONTINUE;
}
});
示例:
Path path1 = Paths.get("file1");
Path path2 = FileSystems.getFileSystem(URI.create("jar:file:/test.jar"))
.getPath("file2");
try {
path1.resolve(path2); // 不同文件系统提供者
} catch(ProviderMismatchException e) {
// 路径来自不同提供者
}
原因:跨不同文件系统提供者操作路径
解决策略:
统一文件系统提供者
转换路径
使用中间操作
// 解决方案示例
Path resolved = path1.resolve(path2.toString());
示例:
try {
System.setSecurityManager(new SecurityManager());
System.exit(0); // 抛出SecurityException
} catch(SecurityException e) {
// 安全策略禁止操作
}
原因:违反安全策略的操作
解决策略:
检查安全权限
使用特权操作
请求必要权限
// 解决方案示例
AccessController.doPrivileged((PrivilegedAction) () -> {
System.setProperty("key", "value");
return null;
});
示例:
try {
Document doc = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
doc.createElement("invalid name"); // 无效元素名
} catch(DOMException e) {
// DOM操作错误
}
原因:XML DOM操作错误
解决策略:
验证DOM操作参数
使用合规XML名称
处理命名空间
// 解决方案示例
public static Element safeCreateElement(Document doc, String name) {
try {
return doc.createElement(name);
} catch(DOMException e) {
return doc.createElement("default");
}
}
示例:
try {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example:type=Test");
mbs.registerMBean(new Test(), name); // 重复注册
} catch(JMXException e) {
// JMX操作失败
}
原因:JMX管理操作失败(如MBean注册/注销问题)
解决策略:
检查MBean命名唯一性
验证MBean接口合规性
使用JMXConnectorServer处理远程访问
// 解决方案示例
public static void registerMBean(Object mbean, String domain, String type) {
try {
ObjectName name = new ObjectName(domain + ":type=" + type);
if(!mbs.isRegistered(name)) {
mbs.registerMBean(mbean, name);
}
} catch(JMXException | MalformedObjectNameException e) {
logger.error("MBean注册失败", e);
}
}
示例:
try {
JAXBContext context = JAXBContext.newInstance(User.class);
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(new User(), new File("user.xml"));
} catch(MarshalException e) {
// XML编组失败
}
原因:对象到XML的编组过程失败
解决策略:
验证对象注解配置
检查XML适配器
处理循环引用
// 解决方案示例
@XmlRootElement
class User {
@XmlTransient // 避免循环引用
public Department department;
}
示例
try {
JAXBContext context = JAXBContext.newInstance(User.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
User user = (User) unmarshaller.unmarshal(new File("invalid.xml"));
} catch(UnmarshalException e) {
// XML解组失败
}
原因:XML到对象的解组过程失败
解决策略:
验证XML结构符合XSD
使用Schema验证
处理日期/数字格式
// 解决方案示例
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File("schema.xsd"));
unmarshaller.setSchema(schema);
示例:
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, null);
try {
services[0].createPrintJob().print(new SimpleDoc(new Printable(){...}, flavor, null));
} catch(PrintException e) {
// 打印服务错误
}
原因:打印系统操作失败
解决策略:
检查打印服务状态
验证文档格式
处理用户取消操作
// 解决方案示例
public static boolean printDocument(Printable printable) {
PrintService service = PrintServiceLookup.lookupDefaultPrintService();
if(service != null) {
try {
DocPrintJob job = service.createPrintJob();
job.addPrintJobListener(new PrintJobAdapter() {
public void printJobFailed(PrintJobEvent pje) {
logger.error("打印失败");
}
});
job.print(new SimpleDoc(printable, DocFlavor.SERVICE_FORMATTED.PRINTABLE, null));
return true;
} catch(PrintException e) {
logger.error("打印错误", e);
}
}
return false;
}
示例:
try {
Font font = Font.createFont(Font.TRUETYPE_FONT, new File("corrupted.ttf"));
} catch(FontFormatException e) {
// 字体文件损坏
}
原因:字体文件格式无效或损坏
解决策略:
验证字体文件完整性
使用系统备用字体
提供字体加载重试机制
// 解决方案示例
public static Font loadFont(File fontFile) {
try {
return Font.createFont(Font.TRUETYPE_FONT, fontFile);
} catch(FontFormatException | IOException e) {
return new Font("Serif", Font.PLAIN, 12); // 返回系统默认字体
}
}
异常转换框架:
public interface ExceptionTranslator {
RuntimeException translate(Exception e);
}
public class JdbcExceptionTranslator implements ExceptionTranslator {
public RuntimeException translate(Exception e) {
if(e instanceof SQLException) {
return new DataAccessException("数据库错误", e);
}
return new SystemException(e);
}
}
错误上下文收集:
public class ErrorContext {
private static ThreadLocal
断路器模式
public class CircuitBreaker {
private final int failureThreshold;
private final long timeout;
private int failures;
private long lastFailureTime;
public T execute(Supplier supplier) throws CircuitBreakerOpenException {
if(System.currentTimeMillis() - lastFailureTime < timeout
&& failures >= failureThreshold) {
throw new CircuitBreakerOpenException("断路器已打开");
}
try {
T result = supplier.get();
reset();
return result;
} catch(Exception e) {
recordFailure();
throw e;
}
}
private void recordFailure() {
failures++;
lastFailureTime = System.currentTimeMillis();
}
private void reset() {
failures = 0;
}
}
异步异常处理:
CompletableFuture.supplyAsync(() -> {
// 可能失败的操作
return fetchData();
})
.handle((result, ex) -> {
if(ex != null) {
logger.error("异步操作失败", ex);
return fallbackData();
}
return result;
})
.thenAccept(this::processResult);