`
snoopy7713
  • 浏览: 1131124 次
  • 性别: 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 常用类解析:java异常机制,异常栈,异常处理方式,异常链,异常丢失详解的相关资料,需要的朋友可以参考下

    java面试题

    这类异常没法要求程序员去一一捕获并抛出,一般异常是Java类库或程序员自己写的代码发生的错误,这类异常可以由我们去一一捕获并抛出。 多线程几种实现方法,同步? 答:多线程有两种实现方法,一种是继承Thread类...

    Java开源的下一代社区平台Symphony.zip

    emoji-java:Java Emoji 处理库 User-Agent-Utils:Java User-Agent 解析库 Druid:Java 数据库连接池 FreeMarker:好用的 Java 模版引擎 Latke:Java Web 框架 NetBeans:全宇宙暂时排名第三的 IDE IntelliJ...

    Java编程艺术 PDF

    1.4 完全集成的异常机制 4 1.5 对多态性支持的改进 5 1.6 通过字节码保证可移植性和安全性 5 1.7 丰富的Java API 6 1.8 Applet 7 1.9 继续变革 7 第2章 递归下降的表达式解析器 9 2.1 表达式 10 2.2 解析表达式 11 ...

    Java面试总结,Redis宕机数据丢失解决方案,看完这篇彻底明白了.docx

    Java面试总结,Redis宕机数据丢失解决方案,看完这篇彻底明白了 本文将从四个方面详细讲解Java面试的重要知识点: 一、Java基础知识 1. HashMap的内部结构、内部原理和HashTable的区别 * HashMap的内部结构主要...

    Java思维导图xmind文件+导出图片

    分布式架构 漫谈分布式架构 初识分布式架构与意义 如何把应用从单机扩展到分布式 大型分布式架构演进过程 分布式架构设计 主流架构模型-SOA架构... Netty无锁化串行设计及高并发处理机制 手写实现多协议RPC框架

    纯java代码实现各种视频转flv格式,支持在线播放。

    纯java代码实现各种视频转flv格式,支持在线播放。不依赖第三方jar包,转码效率高,速度快。

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    java虚拟机栈 50 java堆(Java Heap) 51 方法区 51 【JVM】JVM内存结构,GC垃圾收集解析 52 【JVM】双亲委派模型中,从顶层到底层,都是哪些类加载器,分别加载哪些类? 55 【JVM】能不能自己写个类叫java.lang....

    java_double_serialization:Java double值与字符串,longs,int之间的转换

    基本包函数as.double也可以解析Java的toHexString方法生成的十六进制字符串。 # R version 4.0.5 (2021-03-31) -- "Shake and Throw" # # Some examples of R's as.double parsing hex-strings produced by Java's...

    java 编程艺术

    1.4 完全集成的异常机制 4 1.5 对多态性支持的改进 5 1.6 通过字节码保证可移植性和安全性 5 1.7 丰富的Java API 6 1.8 Applet 7 1.9 继续变革 7 第2章 递归下降的表达式解析器 9 2.1 表达式 10 2.2 解析...

    如何解决java html转pdf图片不显示问题的源码范例合集new(由浅入深代码范例和详细说明).docx

    import java.io.FileOutputStream; public class HtmlToPdfConverter { public static void convertHtmlToPdf(String htmlFilePath, String pdfFilePath) throws Exception { // 创建一个空白的 PDF 文档 ...

    Java与MySQL中小数保存问题解析.pptx.pptx

    在Java和MySQL中,小数的精度可能会受到限制,如float类型的小数只能精确到6-7位,double类型也只能精确到15-16位。 浮点数运算问题 在进行浮点数运算时,可能会出现精度丢失的问题,例如0.1+0.2的结果并不等于0.3...

    精通 Java 必备的 100 道面试题

    精通 Java 必备的 100 道面试题 在 Java 开发中,了解 MySQL 数据库的知识点是非常重要的。本文将通过对 MySQL 的知识点进行总结,帮助 Java 开发者更好地理解 MySQL 的工作原理和应用。 MySQL 的逻辑架构 MySQL ...

    Java基础50题2023新版

    Java基础50题2023新版知识点解析 本资源摘要信息涵盖了Java基础50题2023新版的知识点,涵盖了基础概念、环境变量配置、命令行编程、进制转换、原码补码反码、数据类型转换、算术运算符、浮点数、位运算符、表达式、...

    Java毕业设计-JAVA+SQL离散数学题库管理系统(源代码+论文+外文翻译).rar

    **JAVA+SQL离散数学题库管理系统** 本资源提供了一个基于Java和SQL的离散数学题库管理系统的完整解决方案。该系统旨在帮助教育者和学生更有效地管理和学习离散数学题目。它包括强大的功能,如题目的增删改查、难度...

    JAVA语音通知源码-pascalnide:适用于Android的Pascal编译器

    JAVA语音通知源码Pascal NIDE - 适用于 Android 的 Pascal 编译器 在 Google Play 商店查看应用 概述 该应用程序是 Android 上的 Pascal 解释器。 这个应用程序让大家在没有电脑的情况下在手机上学习Pascal,让我们...

    Java高级架构面试知识点整理.pdf

    或者说,如何处理消息丢失的问题? 5.如何保证消息的顺序性? 6.如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决? 7.如果让你写一个消息队列,该...

    Java POI读取excel中数值精度损失问题解决

    主要介绍了Java POI读取excel中数值精度损失问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    关于C++为什么不加入垃圾回收机制解析

    Java的爱好者们经常批评C++中没有提供与Java类似的垃圾回收(Gabage Collector)机制(这很正常,正如C++的爱好者有时也攻击Java没有这个没有那个,或者这个不行那个不够好),导致C++中对动态存储的官吏称为程序员的...

    DWR.xml配置文件说明书(含源码)

    这有点向java中的import语句,多数类在使用之前需要引入,但引入了类并不意味着这些在使用,每个creator和converter需要有个id属性来允许以后进行引用. 配置文件的allow部分定义哪些类可以建立和转换,每个被准许的类都...

Global site tag (gtag.js) - Google Analytics