概念
1、什么是异常?java提供异常机制有什么用?
程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常
java语言是很完善的语言,提供了异常的处理方式,java把异常打印输出到控制台,供程序员参考、修改,让程序更加健壮。
2、以上程序执行控制台出现的异常信息是JVM打印出来的。
异常的存在形式
/*
java程序中异常以什么形式存在的呢?
1、异常在java中以类的形式存在,每一个异常类都可以创建异常对象
2、异常类是模板
对象是模板
对象是实际存在的个体
*/
public class ExceptionTest02 {
public static void main(String[] args) {
//通过“异常类”实例化“异常对象”
NumberFormatException nfe = new NumberFormatException("数字格式化异常!");
//java.lang.NumberFormatException: 数字格式化异常!
System.out.println(nfe);
//通过“异常类”创建“异常对象”
NullPointerException npe = new NullPointerException("空指针异常发生了!");
//java.lang.NullPointerException: 空指针异常发生了!
System.out.println(npe);
int a = 10;
int b = 0;
//实际上JVM在执行到此处的时候,会new异常:ArithmeticException(/ by zero);
//并且JVM将new的异常对象抛出,打印输出到控制台
int c = a/b;
//java.lang.ArithmeticException: / by zero
//System.out.println(a+"/"+b+"="+c);
}
}
1、异常在java中以类和对象的形式存在。我们可以使用UML图描述一下继承结构。
Object
Object下有Throwable(可抛出的)
Throwable下有两个分支:Error(不可处理,直接退出JVM)和Exception(可处理)
Exception下有两个分支:
Exception的直接子类:编译时异常(要求程序员在编写阶段必须预先对这些异常进行处理,如果不处理编译时异常)
RuntimeException:运行时异常(在编写程序阶段程序员可以预先处理,也可以不管)
2、编译时异常和运行时异常都是发生在运行阶段。编译阶段异常是不会发生的。
3、编译时异常因为什么而得名?
因为编译时异常会在编译阶段预先处理,如果不处理会报错
4、编译时异常和运行时异常的区别?
编译时异常一般发生的概率比较高。
举例子:
你看到外面下雨,倾盆大雨的。
你出门之前会预料到:如果不打伞,我可能会生病(生病是一种异常)
而且这个异常发生的概率很高,所以我们出门之前要拿一把伞
“那一把伞”就是对“生病异常”发生之前的一种处理方式。
运行时异常一般发生的概率比较低。
举个例子:
小明出去被轮子砸到,这个异常发生的概率很低
5、Exception有两个子类:ExceptionSubClass和RuntimeException
6、ExceptionSubClass和RuntimeException的差别
ExceptionSubClass: 所有Exception的直接子类,都叫做编译时异常。编译时异常是表示必须在编写程序的时候预先对这种异常进行处理,如果不处理会报错。编译时异常发生概率较高,又被称为受检异常(ChickenException),还有叫做受控异常
RuntimeException:所有的RuntimeException及其子类都属于运行时异常。运行时异常在编写程序阶段可以处理,也可以不处理。运行时发生的概率很低。运行时异常又被叫做未受检异常(UnCheckedException)、非受控异常
异常的处理
第一种方式:在方法声明的位置上,使用throws关键字
第二种方法:使用try…catch进行异常捕捉
public class ExceptionTest03 {
public static void main(String[] args) {
/*
此处发生了ArithmeticException异常,
底层new了一个ArithmeticException异常对象,
然后抛出了,由于是main方法调用100/0,
所以这个异常ArithmeticException抛给了main方法,
main方法没法处理,然后这个异常自动抛给了JVM。
JVM最终终止程序的执行。
ArithmeticException继承 RuntimeException,属于运行时异常
在运行阶段不需要对这种异常进行预先的处理
*/
System.out.println(100/0);
//这里的HelloWorld没有输出,没有执行
System.out.println("HelloWorld!");
}
}
/*
以下代码报错的原因是什么?
因为doSome方法声明位置上使用了throws ClassCastException
而ClassCastException是编译时异常。必须编写代码时处理,没有处理编译器会报错
*/
public class ExceptionTest04 {
public static void main(String[] args) {
//main方法中调用doSome()方法
//因为doSome()方法声明位置上有throws ClassCastException
//我们在调用doSome()方法的时候必须对这种异常进行预先处理。
//如果不处理,编译器会报错
//
doSome();
}
/**
* doSome方法在声明变量的位置上使用了:throws ClassCastException
* 这个代码表示doSome 在执行过程中,有可能会出现ClassCastException
* 叫做类没找到异常。这个异常直接父类是:Exception,所以ClassCastException属于编译时异常
* @throws ClassCastException
*/
public void doSome() throws ClassCastException{
}
}
public class ExceptionTest05 {
//第一种处理方法:在方法声明的位置上继续使用throws来完成异常的继续上抛。抛给调用者
/*
public static void main(String[] args) throws ClassCastException{
doSome1();
}
*/
//第二种处理方法:try...catch
public static void main(String[] args) {
try{
doSome1();
}catch(ClassCastException e){
e.printStackTrace();
}
}
public static void doSome1() throws ClassCastException{
}
}
异常对象方法
/*
异常对象有两个非常重要的方法:
获取异常简单的描述信息:
String msg = exception.getMessage();
打印异常追踪的堆栈信息:
exception.printStackTrace();
*/
public class ExceptionTest07 {
public static void main(String[] args) {
//这里只是为了测试getMessage()方法和printStackTrace()方法
//这里只是new了一个异常对象,但是没有将异常抛出,JVM认为是一个普通的java对象
NullPointerException e = new NullPointerException("空指针异常2");
//获取异常简单描述信息:这个信息实际上就是构造方法上面的String参数
String msg = e.getMessage();//空指针异常2
System.out.println(msg);
e.printStackTrace();
System.out.println("Hello World!");
}
}