java学习-异常机制
Posted 懒佯佯大哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java学习-异常机制相关的知识,希望对你有一定的参考价值。
异常
-
什么是异常:
- 程序运行过程中出现的错误
-
异常总览:
-
Throwable:
- java语言中所有异常或错误的超类
- 两个子类:
- Error:错误类:是指在程序中了严重问题,不改代码,运行不了
- Exception:异常类:程序一般问题,可以通过处理规避掉
-
常见的Exception:
- NullPointerException:空指针异常
- IndexOutOfBoundsException:越界异常
- ClassCastException:类型转换错误
- RuntimeException:运行期错误
- ConcurrentModificationException:并发修改异常
-
常见的Error:
- OutOfMemoryError:内存超限:比如:int[] a = new int[1000000000];
Throwable详解:
- java语言中所有异常或错误的超类
- 所有继承自Throwable的子类(java自带),都默认使用Throwable的方法(子类基本不实现)
- 其包括如下方法:
方法 | 描述 |
---|---|
public Throwable() | 默认构造函数 |
public Throwable(String message) | 指定消息构造函数,后面该message,可通过getMessage获取 |
public Throwable(String message,Throwable cause) | 可以由message+旧的Throwable对象,构造新的Throwable |
public Throwable(Throwable cause) | 由老的构造,生成新的Throwable |
public String getMessage() | 获取message(简易的) |
public String getLocalizedMessage() | 创建本地化描述,如果不做任何子类实现,其等于getMessage |
public Throwable getCause() | 返回cause |
public Throwable initCause(Throwable cause) | 初始化cause,只能初始化一次 |
public String toString() | 详细描述(jdk文档说是简单描述) |
public void printStackTrace() | 将throwable及其追踪输出至标准输出流 |
public void printStackTrace(PrintStream s) | 将此 throwable 及其追踪输出到指定的输出流。 |
public void printStackTrace(PrintWriter s) | 将此 throwable 及其追踪输出到指定的 PrintWriter。 |
JVM对异常的处理:
- 示例,比如除0异常:
public class Test4
public static void main(String[] args)
int a = 1 / 0;
- 输出:
// 异常的类,以及原因
Exception in thread "main" java.lang.ArithmeticException: / by zero
//出现异常的位置(行)
at Test3.testZero(Test3.java:27)
- 说明:
- 异常也是对象(万物皆对象),JVM发现发生了“除法的除0异常”,将异常封装为java.lang.ArithmeticException:new ArithmeticException(“/ by zero")
- 异常向外抛出,抛到main方法的调用者,即:JVM,此时JVM停止程序,并将异常打印到控制台
异常的详细程度:
- e.printStackTrace() > e.toString() > e.getMessage()
public class Test4
public static void main(String[] args)
try
div(1, 0);
catch (Exception e)
System.out.println("==================== e.getMessage:简要 ====================");
System.out.println(e.getMessage());
System.out.println("==================== e.toString:较详细 ====================");
System.out.println(e.toString());
System.out.println("==================== e.getMessage:非常详细 ====================");
e.printStackTrace();
private static int div(int a, int b)
return a / b;
- 输出:
==================== e.getMessage:简要 ====================
/ by zero
==================== e.toString:较详细 ====================
java.lang.ArithmeticException: / by zero
==================== e.getMessage:非常详细 ====================
java.lang.ArithmeticException: / by zero
at Test4.div(Test4.java:16)
at Test4.main(Test4.java:4)
异常的继承:
- 一般继承如下:并且,基本都使用RuntimeException
/**
* 一般继承时,都覆写空构造器、以及带有message的构造器
*/
class YRuntimeException extends RuntimeException
public YRuntimeException()
super();
public YRuntimeException(String message)
super(message);
异常的捕获:
- 多个异常:
private void testExp()
// 方式1:
try
method();
catch (NullPointerException | ArithmeticException e)
System.out.println(e.toString());
// 方式2:
try
method();
catch (ArithmeticException e)
System.out.println(e.toString());
catch (NullPointerException e)
System.out.println(e.toString());
- 如果多个异常,并且这些异常有父子关系,则父类需要写到最后,否则编译失败
class ExceptionParent extends Exception
class ExceptionSon extends ExceptionParent
class TestException
public static void main(String[] args)
try
throw new ExceptionParent();
catch (ExceptionParent e)
// 这样写,编译器会报错,因为parent异常已经可以捕获了
catch (ExceptionSon e)
Error的捕获
- 因为Error的Exception是两个不同的实现类,故捕获的方式不一样:
class TestY
public static void main(String[] args)
try
int[] a = new int[1000000000];
// 这里会报OutOfMemoryError,只能用Error或者Throwable捕获
catch (Error e)
System.out.println("捕获到异常了");
System.out.println(e.toString());
异常抛出:
- throw:方法内部,手动抛出异常
- throws:方法上,声明本方法抛出的异常类型,调用此方法的必须进行处理
- 运行时异常:RuntimeException或者其子类:
- 特点:运行时异常,方法上不需要throws声明,调用者也不需要处理
class XException extends Exception
class YRuntimeException extends RuntimeException
class TestE
// 只需要抛出XEception即可,RuntimeException及其子类不需要抛出
public void show(int a) throws XException
if (a == 0)
throw new XException();
else
throw new YRuntimeException();
finally
- finally中代码快一定会执行,格式:
- try catch finally
- try finally
- 正常场景:try catch finally都有返回
class TestFinally1
public static void main(String[] args)
System.out.println(show()); // 输出为3
private static int show()
try
return 1;
catch (Exception e)
return 2;
finally
return 3; // finally最终返回的是3
* 过程分析:执行到return 1;时,jvm先预留,不直接返回。等到finlly执行完成后,再返回。此时发现finally里有返回,则按照finally返回,故输出为3.
- 正常场景:finally无返回:
class TestFinally1
public static void main(String[] args)
System.out.println(show1()); // 返回为1
private static int show1()
try
return 1; // 最后返回这里
catch (Exception e)
return 2;
finally
System.out.println("no return”); // 首先,会打印这里
输出:
no return
1
- 异常场景:无finally,最终按照catch中返回
private static int showException()
try
int a = 1 / 0;
return 1;
catch (Exception e)
return 2; // 最终方法返回的是这里
- 异常场景:有finally:则按照finally中返回
private static int showException()
try
int a = 1 / 0;
return 1;
catch (Exception e)
return 2;
finally
return 3; // 最终返回的是这里:3
注意:这里逻辑比较绕,但最好不要在finally中写return
继承关系中方法的异常处理:
- 父类方法没有异常,则子类继承的方法也不能有:
class A
public void show()
class B extends A
// 正确写法:
@Override
public void show()
// 错误写法:
// @Override
// public void show() throws ExceptionSon
//
- 父类方法有异常,则子类:
- 可以不写
- 或者声明为该异常的子类(异常的父类会报错)
class AException extends Exception
class BException extends AException
class A
public void show() throws AException
class B extends A
// 正确写法1:不抛异常
// @Override
// public void show()
//
// 正确写法2:抛出为父类异常的子类
@Override
public void show() throws BException
// 错误写法:抛出的异常比父类要高
// @Override
// public void show() throws Exception
//
以上是关于java学习-异常机制的主要内容,如果未能解决你的问题,请参考以下文章