1异常
- 异常都继承于Exception
- 用分为运行时异常(RuntimeException)和非运行时异常
- 运行时异常由JVM自动抛出,非运行时异常手动抛出(throw)
finally中的代码块一定会执行
1.1异常的捕获和处理
用:try{
会出现异常的代码
}catch(异常类){处理代码}
例:
public static void main(String[] args) {
di();
}
//示例方法
public static void di(){
int a = 3/0;
}
因为0不能做除数,所以调用di()方法是执行到这句会报错:
java.lang.ArithmeticException: / by zero
at te.st.yichang.Test1.di(Test1.java:16)
at te.st.yichang.Test1.main(Test1.java:7)
所以可以用try,catch语句块来捕获和处理。例:
//用try,catch来捕获处理
try {
di();
} catch (ArithmeticException e) {
System.out.println("这是我自己处理的异常");
}
输出的结果是:这是我自己处理的异常
1.11异常类有两个方法好用的方法:
e.getMessage():获取导致异常的消息
e.printStackTrace():打印导致异常的路径和消息
例:
//用try,catch来捕获处理
try {
di();
} catch (ArithmeticException e) {
String str = e.getMessage();
System.out.println(str);
e.printStackTrace();
}
输出:
/ by zero
java.lang.ArithmeticException: / by zero
at te.st.yichang.Test1.di(Test1.java:18)
at te.st.yichang.Test1.main(Test1.java:7)
1.2运行时异常
运行时异常有JVM自动抛出,它会一直往上抛,直到程序结束,然后直接终止程序
例:写一个类继承RuntimeException,
/*
* 写一个类继承于RuntiamException
* */
class MyRuntimeException extends RuntimeException{
//
public void di(){
int a = 3/0;
}
}
main入口:
public static void main(String[] args) {
//实例化
MyRuntimeException me = new MyException();
//
me.di();
System.out.println("我是语句块外面的");
}
输出结果是:直接报错终止程序
Exception in thread "main" java.lang.ArithmeticException: / by zero
at te.st.yichang.MyException.di(Test4.java:21)
at te.st.yichang.Test4.main(Test4.java:8)
System.out.println("我是语句块外面的");
这句话就没有被执行
这是应为运行时异常是直接向上抛出的,执行到int a = 3/0时发现异常,JVM直接抛到main方法中,main方法中又没有捕获和处理这个异常,又向上面抛,由于mian上面已经无处可抛,就直接终止程序,main中di()后面的语句就不会执行;
用try,catch捕获处理就不会了:
修改main:用try,catch捕获
public static void main(String[] args) {
//实例化
MyException me = new MyException();
//
try {
me.di();
} catch (ArithmeticException e) {
System.out.println("我已经捕获处理了该异常");
}
System.out.println("我是语句块外面的");
}
输出结果:
我已经捕获处理了该异常
我是语句块外面的
1.3,finally语句块
finally语句块内的语句一定会执行
例:
在try,catch的di()语句后面添加一句
try {
me.di();
System.out.println("我是语句块内的");//添加一句
} catch (ArithmeticException e) {
System.out.println("我已经捕获处理了该异常");
}
输出的还是:
我已经捕获处理了该异常
因为在try,catch中,前面的语句捕获到异常时,该语句后面的语句就不在去执行了,而是直接跳出语句块
所以需要添加finally
例:将其移到finally中
//
try {
me.di();
} catch (ArithmeticException e) {
System.out.println("我已经捕获处理了该异常");
}finally{
System.out.println("我是语句块内的");
}
输出结果:
我已经捕获处理了该异常
我是语句块内的
1.4非运行时异常
还有一种异常叫非运行时异常,这就需要程序员手动抛出,用throw关键字
有两种方式:
第一种:直接try,catch捕获处理
第二种:往上抛出,声明该方法为会产生异常,用throws关键(比throw多个s)
例:1写一个类,继承Exception
/*
* 我自己写的异常,继承Exception
* */
class MyException extends Exception{
public MyException() {
super();
// TODO Auto-generated constructor stub
}
public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public MyException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public MyException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public MyException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
2,Buy类,这里面的方法会产生异常:
class Buy{
//身高
int high;
//买衣服的方法
//size判断衣服是否合身,不合身就报异常
public void clothes(int size) throws MyException{//这里我将异常声明在方法中抛出
if(size==high){
System.out.println("这件衣服很合身");
}else if(size>high){
//大了就好比一个异常
//用throw抛出,throw new一个异常类
//当用了throw时,就要处理这个异常,是要try,cath还是抛出,如果抛出就要在方法中用throws声明要抛出的异常类
throw new MyException("衣服大了!");
}else{
throw new MyException("衣服小了");
}
}
}
main:
public static void main(String[] args){
Buy buy = new Buy();
buy.high = 170;
//调用的这个方法会产生异常,因为我在这个法中声明了会抛出MyException异常
//两种处理方式
//第一种,直接捕获处理
try {
buy.clothes(190);
} catch (MyException e) {
System.out.println(e.getMessage());
}
}
这里会输出:衣服大了
第二种就是再次向上抛出:
public static void main(String[] args) throws MyException{//这种就需要在这个会出异常的方法中声明要抛出的异常
Buy buy = new Buy();
buy.high = 170;
//调用的这个方法会产生异常,因为我在这个法中声明了会抛出MyException异常
//两种处理方式
//第二种,不处理往上抛出
buy.clothes(190);
}
输出结果:Exception in thread "main" te.st.yichang.MyException: 衣服大了!
at te.st.yichang.Buy.clothes(Test4.java:31)
at te.st.yichang.Test4.main(Test4.java:11)
对比两种,运行时异常就不用我们手动抛出,非运行时异常就要我们手动抛出,直到我们处理了这个异常或抛到最顶层(一般都是不会在main方法中再次抛出异常,这里只是示例)
1.5异常的多态
异常也是类,都是继承Exception所以异常也会有多态
要在try,catch中使用中注意
例:1,在写了一个异常类MyException2继承Exception,这里就不贴了(方法同上)
2,修改下Buy类。将衣服小了抛出MyException2,并该方法声明抛出throws Exception
public void clothes(int size) throws Exception{//这里改为抛出Exception
if(size==high){
System.out.println("这件衣服很合身");
}else if(size>high){
throw new MyException("衣服大了!");
}else{
//这里改为抛出MYException2
throw new MyException2("衣服小了");
}
}
3main:中就要捕获两个异常,
最后还要捕获父类的异常
//捕获处理异常
try {
buy.clothes(190);
//买件小衣服
buy.clothes(120);
} catch (MyException e) { //捕获MyException
System.out.println(e.getMessage());
}catch(MyException2 e){ //捕获MyException2
System.out.println(e.getMessage());
}catch(Exception e){ //记住,最后还要捕获父类异常
System.out.println(e.getMessage());
}