一、异常
异常概述:异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序。简单来说就是程序出现了不正常的情况。异常本质就是Java当中对可能出现的问题进行描述的一种对象体现。
常见异常:
除数不能为0异常(ArithmeticException)
空指针异常(NullPointException)
数组越界异常(ArrayIndexOutOfBoundsException)
类型转换异常(ClassCastException)
Error:称为错误,由Java虚拟机生成并抛出,程序对其不做处理。
异常分类
-
Exception:所有异常类的父类,其子类对应了各种各样可能出现的异常事件,一般需要用户显示的声明或捕获。
-
RuntimeException:运行时期异常,又称为非受检异常,RuntimeException及其所有子类都是运行时期异常。
-
编译时期异常:不是继承自RuntimeException的Exception的子类都成为编译时期异常。
处理异常的目的:
并不是为了修复程序的错误,而是就算程序出现了错误,也能够让程序继续执行
虚拟机的处理方式:
把异常的名称,异常出现的位置,异常原因,等信息输出打印在控制台,并同时将 程序停止执行。
如果我们不做任何处理,异常将会交由虚拟机来处理,JVM处理异常的方式不能够满足我们开发的需求,那么我们需要自己处理异常
我们自己处理异常的方式:
1、try…catch…finally
2、throws抛出异常
单个异常的处理
try…catch…finally的处理格式:
异常处理的格式:
try{
//放置程序可能出现问题的代码
}catch(异常类 异常名){
//这里放置异常处理的代码
} finally{
//释放资源
}
注意:
- 1.try块的代码越少越好
- 2.try块中一旦发生异常,那么try块中发生异常后面所有的代码都不会被执行
- 3.多个catch块只会执行一个
- 4.Exception接受异常必须放在异常的最后面,满足先子类后父类
异常的执行流程:
- 1.程序执行到错误行,系统会创建一个异常对象,并且抛给我们
- ArithmeticException exp = new ArithmeticException("/by zero");
- throw exp;
- 2.程序进入catch块进行逐个匹配
- 匹配成功,程序执行catch块代码
- ArithmeticException ae = exp;
- Exception e = exp;
- 匹配失败,交给jvm处理
处理异常的标准方式:
- 1.能够显示处理的尽量显示处理,提高程序的可读性
- 2.但是一定要在异常处理的最后加上 父类Exception处理
二、Throwable 类
Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。
成员方法
public String getMessage():返回此 throwable 的详细消息字符串
public String toString():获取异常类名和异常信息。
public void printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置。
public void printStackTrace(PrintStream s):通常用该方法将异常内容保存在日志文件中,以便查阅
public class ExceptionDemo {
public static void main(String[] args) throws FileNotFoundException {
Throwable throwable = new NullPointerException();
Throwable throwable = new ArithmeticException("除数不能为0");
String message = throwable.getMessage();
System.out.println(message);
System.out.println(throwable.toString()); // java.lang.ArithmeticException: 除数不能为0
public void printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置。
throwable.printStackTrace();
public void printStackTrace(PrintStream s):通常用该方法将异常内容保存在日志文件中,以便查阅。
throwable.printStackTrace(new PrintWriter("a.txt"));
StackTraceElement[] stackTrace = throwable.getStackTrace();
for (int i = 0; i < stackTrace.length; i++) {
System.out.println(stackTrace[i].getMethodName() + "|" + stackTrace[i].getClassName() + "|" + stackTrace[i].getLineNumber() + "|" + stackTrace[i].getFileName()) ;
}
}
}
1.Throws关键字
Throws关键字概述
在定义一个方法的时候可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用者进行处理。
throws使用格式
[修饰符] 返回值类型 方法名(参数列表) [throws 异常类1,异常类2…]{
}
注意:
1、如果一个方法声明的是编译时期异常,则在调用这个方法之处必须处置这个异常(谁调用该有问题的方法谁处理)。
2、重写一个方法时,它所声明的异常范围不能被扩大。
public class ExceptionDemo {
public static void main(String[] args) {
try {
calc();
} catch (Exception e) {
e.printStackTrace();
}
try {
method();
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("00000000000000000");
}
public static int calc() throws ArithmeticException{
int a = 10;
int b = 0;
int result = a/b;
return result;
}
public static void method() throws ParseException{
String s = "2018-04-28";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM/dd");
sdf.parse(s);
}
}
class Father{
public void show() throws Exception{
}
}
class Son extends Father{
@Override
public void show() throws NullPointerException,ArithmeticException,ClassCastException {
}
}
Throw关键字
在方法代码中主动抛出一个异常。如果方法代码中自行抛出的异常是编译时期异常,则这个方法要用throw关键字声明这个异常。
格式:
- throw 异常对象;
- 谁调用就将对象抛给谁
- 当抛出的是编译时异常的时候,必须要在方法体上声明异常
- 当时运行时异常的时候,可以不用声明,但是建议声明
Throws和Throw的区别
- 1.throws用在方法声明后面,跟的是异常类名,throw用在方法体内,跟的是异常对象名。
- 2.throws可以跟多个异常类名,用逗号隔开,throw只能抛出一个异常对象名。
- 3.throws表示抛出异常,由该方法的调用者来处理,throw表示抛出异常,由方法体内的语句处理。
- 4.throws表示出现异常的一种可能性,并不一定会发生这些异常,throw则是抛出了异常,执行throw则一定抛出了某种异常。
public class ExceptionDemo {
public static void main(String[] args) {
String s = new String(new byte[] {11,22,33,44}, -1, 3);
System.out.println(s);
try {
calc();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("go on");
}
private static void calc() throws CloneNotSupportedException {
int a = 10;
int b = 0;
// 方式一处理异常:
// if (b != 0) {
// System.out.println(a / b);
// }
// 方式二处理异常:
if (b == 0) {
throw new CloneNotSupportedException("除数不能为0");
}
System.out.println(a / b);
}
}
finally关键字
1.finally修饰的代码块一定会被执行,除非在执行到finally之前程序异常退出或者调用了系统退出的方法。如:System.exit(0);Runtime.getRuntime().exit(0);
2.finally用于释放资源,比如关闭IO流的输入输出对象,数据库连接对象等。
public class FinallyTest {
public static void main(String[] args) {
System.out.println(test());
}
public static int test() {
int x = 1;
try {
x++;
return x;
} finally {
++x;
System.out.println(x);
}
}
}
finalize()方法,finally关键字,final关键字的区别
1.finalize()方法
- 当垃圾回收器确定不存在对该对象的更多引用时,
- 由对象的垃圾回收器调用此方法。用于垃圾回收,但是什么时候回收不确定。
2.final
- final修饰的变量表示常量,不能够被二次赋值
- final修饰的类不能够被继承
- final修饰的方法不能够被子类重写
3.finally
- 一般用来释放内存资源(io流的端口,网络的端口,数据库的连接断开等等)
三、自定义异常
自定义异常的步骤
- 1.创建一个异常类继承 Exception或者RuntimeException
- 2.在自定义异常类中书写构造方法即可
a.无参构造
b.带错误信息的构造方法
**举例:**自定义一个异常,要求考试成绩必须在0-100之间,如果不在这个范围内,抛出异常。自定义异常:继承自Exception
public class ExceptionDemo {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入一个分数:");
double score = input.nextDouble();
Teacher teacher = new Teacher();
try {
System.out.println(teacher.isBetween0To100(score) ? "分数合法" : "分数不合法");
} catch (ScoreException e) {
// e.printStackTrace();
System.err.println(e.getMessage());
} catch (Exception e) {
e.printStackTrace();
} finally {
input.close();
}
System.out.println("分数批改完毕!");
}
}
class ScoreException extends Exception{
public ScoreException(){}
public ScoreException(String message) {
super(message);
}
}
class Teacher{
public boolean isBetween0To100(double score) throws ScoreException{
if (score > 100 || score < 0) {
throw new ScoreException("分数必须在0-100分之间!!!");
}
return true;
}
}