`
snoopy7713
  • 浏览: 1154339 次
  • 性别: Icon_minigender_2
  • 来自: 火星郊区
博客专栏
Group-logo
OSGi
浏览量:0
社区版块
存档分类
最新评论

java常用类解析七:java异常机制、异常栈、异常处理方式、异常链、异常丢失

    博客分类:
  • java
阅读更多
package demo.others;

import mine.util.exception.MyException;

public class ExceptionDemo1 {
	public void f() throws MyException {
		throw new MyException("自定义异常");
	}

	public void g() throws MyException {
		f();
	}

	public  void h() throws MyException  {
		try {
			g();
		} catch (MyException e) {
			//1、通过获取栈轨迹中的元素数组来显示异常抛出的轨迹
			for (StackTraceElement ste : e.getStackTrace())
				System.out.println(ste.getMethodName());
			//2、直接将异常栈信息输出至标准错误流或标准输出流
			e.printStackTrace();//输出到标准错误流
			e.printStackTrace(System.err);
			e.printStackTrace(System.out);
			//3、将异常信息输出到文件中
			//e.printStackTrace(new PrintStream("file/exception.txt"));
			//4、重新抛出异常,如果直接抛出那么栈路径是完整的,如果用fillInStackTrace()
			//那么将会从这个方法(当前是h()方法)作为异常发生的原点。
			//throw e;
			throw (MyException)e.fillInStackTrace();
		}
	}
	public static void main(String[] args) {
			try {
				new ExceptionDemo1().h();
			} catch (MyException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
}
 

1、java标准异常概述

Throwable表示任何可以作为异常被抛出的类,有两个子类Error和 Exception。从这两个类的源代码中可以看出,这两个类并没有添加新的方法,Throwable提供了所以方法的实现。Error表示编译时和系统 错误。Exception是可以被抛出的异常类。RuntimeException继承自Exception(如 NullPointerException),表示运行时异常,JVM会自动抛出.

2、自定义异常类

自定义异常类方法: 通过继承Throwable或Exception。异常类的所有实现都是基类Throwable实现的,所以构造自定义异常类完全可以参考Exception和Error类。我们只要添加上自定义异常类的构造方法就可以了

package demo.others;

/**
 * 自定义异常类方法
 * 1、通过继承Throwable
 * 2、通过继承Exception
 * 
 * @author Touch
 */
public class MyExceptionDemo extends Exception {

	private static final long serialVersionUID = 1L;

	public MyExceptionDemo() {
		super();
	}

	public MyExceptionDemo(String message) {
		super(message);
	}

	public MyExceptionDemo(String message, Throwable cause) {
		super(message, cause);
	}

	public MyExceptionDemo(Throwable cause) {
		super(cause);
	}
}
 

3、异常栈及异常处理方式

可以通过try、catch来捕获异常。捕获到的异常。下面的示例演示了几种常用异常处理方式

运行结果:

f
g
h
main
mine.util.exception.MyException: 自定义异常
 at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7)
 at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11)
 at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)
 at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)
mine.util.exception.MyException: 自定义异常
 at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7)
 at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11)
 at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)
 at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)
mine.util.exception.MyException: 自定义异常
 at demo.others.ExceptionDemo1.f(ExceptionDemo1.java:7)
 at demo.others.ExceptionDemo1.g(ExceptionDemo1.java:11)
 at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:16)
 at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)
mine.util.exception.MyException: 自定义异常
 at demo.others.ExceptionDemo1.h(ExceptionDemo1.java:30)
 at demo.others.ExceptionDemo1.main(ExceptionDemo1.java:35)

分析上面的程序,首先main函数被调用,然后是调用h函数,再g函数、f函数,f函数抛出异常,并在h函数捕获,这时将依次从栈顶到栈底输出异常栈路径。

4、异常链

有时候我们会捕获一个异常后在抛出另一个异常,如下代码所示:

package demo.others;

import java.io.IOException;

import mine.util.exception.MyException;

public class ExceptionDemo2 {
	public void f() throws MyException {
		throw new MyException("自定义异常");
	}

	public void g() throws Exception  {
		try {
			f();
		} catch (MyException e) {
			e.printStackTrace();
			throw new Exception("重新抛出的异常1");
		}
	}

	public  void h() throws IOException    {
		try {
			g();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new IOException("重新抛出异常2");
		}
	}
	public static void main(String[] args) {
			try {
				new ExceptionDemo2().h();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
}

 运行结果:

mine.util.exception.MyException: 自定义异常
 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)
java.lang.Exception: 重新抛出的异常1
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)
java.io.IOException: 重新抛出异常2
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:32)

从结果中我们可以看出,异常栈变小了。也就是说丢失了最原始的异常信息。怎样保存最原 始的异常信息呢?Throwable类中有个Throwable  cause属性,表示原始异常。通过接收cause参数的构造器可以把原始异常传递给新异常,或者通过initCause()方法。如下示例:

package demo.others;

import java.io.IOException;

import mine.util.exception.MyException;

public class ExceptionDemo2 {
	public void f() throws MyException {
		throw new MyException("自定义异常");
	}

	public void g() throws Exception  {
		try {
			f();
		} catch (MyException e) {
			e.printStackTrace();
			throw new Exception("重新抛出的异常1",e);
		}
	}

	public  void h() throws IOException    {
		try {
			g();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			IOException io=new IOException("重新抛出异常2");
			io.initCause(e);
			throw io;
		}
	}
	public static void main(String[] args) {
			try {
				new ExceptionDemo2().h();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
}
 

结果:

mine.util.exception.MyException: 自定义异常
 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)
java.lang.Exception: 重新抛出的异常1
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)
Caused by: mine.util.exception.MyException: 自定义异常
 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
 ... 2 more
java.io.IOException: 重新抛出异常2
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:27)
 at demo.others.ExceptionDemo2.main(ExceptionDemo2.java:34)
Caused by: java.lang.Exception: 重新抛出的异常1
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:17)
 at demo.others.ExceptionDemo2.h(ExceptionDemo2.java:23)
 ... 1 more
Caused by: mine.util.exception.MyException: 自定义异常
 at demo.others.ExceptionDemo2.f(ExceptionDemo2.java:9)
 at demo.others.ExceptionDemo2.g(ExceptionDemo2.java:14)
 ... 2 more

从结果中看出当获取到“重新抛出异常2的时候,同时可以输出原始异常“重新抛出的异常1“和原始异常”自定义异常,这就是异常链。

5、finally的使用

finally子句总是执行的,通常用来做一些清理工作,如关闭文件,关闭连接等

下面举几个finally的例子:

// 读取指定路径文本文件
	public static String read(String filePath) {
		StringBuilder str = new StringBuilder();
		BufferedReader in = null;
		try {
			in = new BufferedReader(new FileReader(filePath));
			String s;
			try {
				while ((s = in.readLine()) != null)
					str.append(s + '\n');
			} finally {
				in.close();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return str.toString();
	}
 

分析:如果调用in = new BufferedReader(new FileReader(filePath));时发生异常,这时是一个文件路径不存在的异常,也就是说并没有打开文件,这时将会直接跳到catch块,而 不会执行try...finally块(并不是finally子句)里面的语句in.close();此时不需要关闭文件。

再看一个例子,会导致异常的丢失

package demo.others;

import mine.util.exception.MyException;

public class ExceptionDemo3 {
	public void f() throws MyException {
		throw new MyException("异常1");
	}

	public void g() throws MyException {
		throw new MyException("异常2");
	}

	public static void main(String[] args) {

		try {
			ExceptionDemo3 ex = new ExceptionDemo3();
			try {
				ex.f();
			} finally {
				ex.g();//此时捕获g方法抛出的异常,f方法抛出的异常丢失了
			}
		} catch (MyException e) {
            System.out.println(e);
		}

	}
}
 

结果:mine.util.exception.MyException: 异常2

此时异常1就丢失了
或者这样写:

package demo.others;

import mine.util.exception.MyException;

public class ExceptionDemo3 {

	public void g() throws MyException {
		throw new MyException("异常2");
	}

	public static void main(String[] args) {
		ExceptionDemo3 ex = new ExceptionDemo3();
		try {
			ex.g();
		} finally {
			//直接return会丢失所以抛出的异常
			return;
		}

	}
}
 

6、异常的限制

(1)当覆盖方法时,只能抛出在基类方法的异常说明里列出的那些异常,有些基类的方法声明抛出异常其实并没有抛出异常,这是因为可能在其子类的覆盖方法中会抛出异常

(2)构造器可以抛出任何异常而不必理会基类构造器所抛出的异常,派生类构造器异常说明必须包含基类构造器异常说明,因为构造派生类对象时会调用基类构造器。此外,派生类构造器不能捕获基类构造器抛出的异常。

分享到:
评论

相关推荐

    Java 常用类解析:java异常机制,异常栈,异常处理方式,异常链,异常丢失详解

    异常栈是 Java 语言中的一种异常处理机制,它允许开发者捕获和处理异常。异常栈可以通过 try、catch 语句来捕获异常,并且可以使用 printStackTrace() 方法来输出异常信息。 6. 异常处理方式 Java 提供了多种异常...

    Java面试解析总结:Java+Redis+数据库+解决方案+分布式...docx

    ### Java面试解析总结 #### 数据库篇 - **事务四大特性(ACID)**:事务在数据库操作中扮演着至关重要的角色,确保数据的一致性和完整性。ACID特性包括: - **原子性(Atomicity)**:表示事务中的所有操作要么...

    Java版DLT645-2007电能表协议解析源码(串口协议解析)

    6. **异常处理**:在实际应用中,串口通信可能会遇到各种异常情况,如连接丢失、超时等,需要编写相应的异常处理代码来保证程序的健壮性。 有了这些基本理解,开发者就可以着手实现一个能够与DLT645-2007兼容的电能...

    Java常用基础知识-kaic.docx

    Java 常用基础知识是程序员面试中不可或缺的部分,尤其对于准备进入阿里巴巴、腾讯、京东、...在学习和实践中,不断加深对Java虚拟机、异常处理、类加载机制以及Java跨平台特性的理解,将有助于提升解决问题的能力。

    Java常见异常总结

    为了帮助开发者更好地理解和处理这些异常,本文将深入探讨一系列常见的Java异常,涵盖从基本的`ArithmeticException`到复杂的`TypeInitializationException`,以及一些特定于类型或操作的异常。通过理解每种异常的...

    简单好用的前台异常提示jsp

    标题中的“简单好用的前台异常提示jsp”指的是在Web开发中,...通过阅读这篇博客,开发者可以学习到如何在实际项目中优雅地处理异常,提高用户体验,并且了解到如何利用Java工具类和JSP页面进行有效的错误信息传递。

    java所有运行时异常以及错误.doc

    Java 作为一种广泛使用的编程语言,其强大的异常处理机制确保了程序的健壮性和稳定性。在 Java 中,异常主要分为两大类:**运行时异常**(RuntimeException)和 **错误**(Error)。本文将详细介绍这些异常的具体...

    java 下载的页面不丢失链接

    首先,Java中的`java.net`包提供了必要的类来处理网络连接,如`HttpURLConnection`和`URL`。`URL`类用于表示统一资源定位符,即网页的地址,而`HttpURLConnection`则可以用来建立到该URL的连接并进行各种HTTP操作,...

    java sip 协议栈实现客户端和服务

    此外,还可以深入了解网络编程、多线程处理、异常处理等相关Java编程技巧,以及如何处理实时通信中的各种问题,如网络延迟、数据包丢失等。这个项目为学习和实践SIP协议提供了一个很好的平台,对于提升Java程序员在...

    id3-java.rar_JAVA weather mysql_site:en.pudn.com

    7. **Java异常处理**:在处理网络请求和数据库操作时,会涉及到异常处理,以确保程序的健壮性。 8. **文件操作**:"copia - copia"可能涉及到文件复制或备份操作,使用Java的File类和相关方法。 9. **版本控制**:...

    java解析word文件的相关代码

    ### Java解析Word文件的关键知识点 #### 一、POI库介绍 - **定义与来源**:POI是Apache软件基金会的Jakarta项目中的一个子项目,它提供了一组API,用于处理Microsoft Office格式的文件(如Word、Excel)。POI支持...

    java调用C++ webservice

    - 错误处理是关键,需要处理网络、SOAP解析、服务端异常等可能的问题。 - 注意不同平台之间的编码差异,确保数据传输过程中不丢失或错误。 6. **示例代码**: - 假设已生成了名为`WebServiceClientStub.java`的...

    JAVA个人资料JAVA

    7. **多线程+操作系统**:这部分可能探讨了Java如何处理并发,如Thread类的使用、同步机制(synchronized关键字、wait/notify、ReentrantLock等),以及线程池的概念。结合操作系统,可能会讨论线程调度、上下文切换...

    java解析DLT645源码

    Java解析DLT645源码是一个关于电力自动化领域通信协议处理的主题。DLT645,全称为“Discrete Local Telecommunications - 645”,是一种广泛应用于电能表和其他能源管理设备的通信协议。它允许设备与主站系统进行...

    基于javaswing的体温检测系统

    9. **异常处理**:在进行文件读写时,系统应包含异常处理机制,以应对可能出现的文件不存在、权限问题或数据格式错误等情况,确保程序的稳定运行。 10. **用户界面设计**:Java Swing提供了丰富的组件如按钮、...

    Java定时任务实现解析.pptx.pptx

    本篇将深入解析Java定时任务的原理、常见实现方式以及应用场景,并对它的优缺点进行分析。 一、Java定时任务简介 Java定时任务是一种编程机制,能够帮助开发者实现按需执行的任务,这些任务可能是周期性的或一次性...

    Java 解析 pdf文件用到的jar包

    总结来说,Java解析PDF文件的关键在于利用PDFBox和FontBox这两个库。PDFBox提供了一套强大的工具集,用于读取、修改和创建PDF文档,而FontBox则专注于处理PDF中的字体,确保文本的正确呈现。通过熟练掌握这两个库,...

    C++代码转java工具

    4. **异常处理**:将C++的错误处理机制(如返回错误码)转换为Java的异常处理机制。 5. **内存管理**:C++使用手动内存管理,而Java有自动垃圾回收,工具需要处理这两者之间的差异。 6. **函数调用和库集成**:如果...

    java常用语句大全java编码规范模拟测验答案

    ### Java常用语句大全及Java编码规范模拟测验解析 #### 集合类的使用规范 1. **集合类的命名原则** - 正确做法:含有集合意义的属性命名,尽量包含其复数的意义。例如,存储员工信息的列表可以命名为`employees`...

Global site tag (gtag.js) - Google Analytics