11、异常的捕获与处理
程序开发中,程序的编译和运行是两个阶段,编译主要是针对语法检测,运行出现的错误导致程序中断运行,这种错误称为异常。
异常是指程序运行时由于程序处理逻辑上的错误导致程序中断的一种指令流。
异常处理关键字:try、catch、finally
try{ //有可能出现异常的语句
}[catch (异常类型 对象){
//异常处理
}catch(异常类型 对象){
//异常处理
}…][finally{
//不管是否异常都执行的统一代码
}]
如果在try语句中捕获到异常,程序会自动跳转到catch语句找到匹配的异常类型进行相应处理。最后不管程序是否出现异常,都会执行finally语句,finally语句作为异常的统一出口。
catch(ArithmeticException e){//捕获算数异常
e.printStackTrace();//输出异常信息,明确告诉用户哪一行代码出现异常
}
finally作用往往是在开发中进行一些资源释放操作
(1) java中可以处理的异常都是程序运行中产生的异常,当程序运行到某行代码出现异常,由JVM帮助用户判断此异常的类型,并自动进行执行类型的异常类对象实例化处理。
(2) 如果程序没有提供异常处理支持,会采用JVM默认异常处理方式,首先进行异常信息的打印,然后直接退出当前程序。
(3) 如果程序中存在异常处理,产生的异常类的实例化对象会被try捕获。
(4) try捕获异常之后与其匹配的catch中的异常类型进行比对。
(5) 不管异常是否处理最终都要执行finally语句,当执行完成finally程序之后进一步判断当前的异常是否已经处理过了,如果处理过了则继续执行其他代码,如果没有处理则交给JVM进行默认处理。
整个异常处理流程实际上操作的还是一个异常类的实例化对象,异常类最高的继承类是Throwable,它有两个子类:
Error:JVM错误,这个时候程序没有执行,无法处理。 Exception:程序运行中产生的异常,用户可以使用异常处理格式进行处理。
开发中用户可以处理的异常都要求以Exception为主。
简化异常处理:
catch(Exception e){ //处理所有异常
e.printStackTrace();
}
处理多个异常时,捕获范围小的异常要放在捕获范围大的异常之前处理,例如:
catch(ArithmeticException e){
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
程序执行过程中往往涉及不同类中方法的调用,为了方便调用者进行异常的处理,会在这些方法声明时对可能产生的异常进行标记,用到throws关键字。
class MyMath{
public static int div(int x,int y) throws Exception{
return x/y;
}
}
…
try{//调用throws方法时需要进行异常处理
System.out.print(MyMath.div(10,2));
}catch(Exception e){
e.printStackTrace();
}
考虑代码的统一性,不管调用方法时是否产生异常,都必须进行异常处理操作。
如果主方法中使用throws抛出异常,表示主方法可以不用强制性进行异常处理,如果出现异常,将交给JVM进行默认处理,此时会导致程序中断执行。
异常处理中会自动实例化异常类的对象,很多时候开发者在进行更加深入设计时需要进行手动异常处理,用到throw关键字。
try{
throw new Exception(“自己设计的对象”);
}catch(Exception e){
e.printStackTrace();
}
异常处理模型:异常交给调用处处理
为了方便用户代码的编写,RuntimeException异常类可以让程序在编译的时候不会强制性要求用户处理异常,用户可以根据自己的需要进行异常的选择性处理。如果出现异常又没有处理,则交给JVM默认处理。
字符串转换int:
public static int parseInt(String s) throws NumberFormatException;
调用时不处理也不会出现编译语法错误。
用户可以自己定义一个异常类,需要继承Exception(强制性异常处理)或RuntimeException(选择性异常处理)。
class BombException extends Exception{
public BombException(String msg){
super(msg);//调用父类构造
}
}
class Food{
public static void eat(int num) throws BombException{
if(num>999){
throw new BombException(“1”);
}else{
System.out.println(“2”);
}
}
}
public class Javademo{
public static void main(String args[]){
try{
Food.eat(11);
}catch(BombException e){
e.printStackTrace();
}
}
}
**断言(assert)**是指程序执行到某行之后,其结果一定是预期的结果。
assert x==100:“x的内容不是100”;
Java默认情况不开启断言,如果要启动断言需要增加:
java -ea cn.demo.Javademo
12、内部类
内部类是一种常见的嵌套结构,利用这种结构使得内部类可以与外部类共存,并方便进行私有操作的访问,内部类也可以进一步扩展到匿名内部类的使用。
class Outer{
private String msg=”xxx”;
public void fun(){
Inner in=new Inner();
in.print();
}
class Inner{
public void print(){
System.out.println(Outer.this.msg);//内部类直接输出外部类的msg私有成员属性
}
}
}
public class JavaDemo{
public static void main(String args[]){
Outer out=new Outer();
out.fun();
}
}
外部类可以访问内部类私有成员,内部类被外部类包裹,但是其本身也属于一个完整类,可以直接进行内部类对象的实例化。
外部类.内部类 内部类对象=new 外部类().new 内部类();
Outer.Inner in=new Outer().new Inner();//实例化内部类对象
内部类私有化:如果一个内部类不想被其他类使用,用private关键字将内部类定义为私有内部类。该类只允许被Outer一个类使用。
private class Inner{ }
(未完待续…)