异常

异常是什么?

1.异常模拟的是现实世界中的“不正常”事件

2.java中采用“类”去模拟异常

3.类是可以创建对象的

异常的作用?

程序发生异常事件后(比如空指针),为我们输出详细的信息,程序员通过这个信息,可以对程序进行一些处理,使程序更加健壮

前面的代码发生了异常并且没有处理,那么下面的代码也不会执行了,直接退出JVM

public class Test01 {

    public static void main(String[] args) {
        int m = 10 ; 
        int n = 0 ;
        
        System.out.println(m/n);
        
        System.out.println("hello world"); //不会输出
    }
    
}

如果捕获异常后可以,比如

package exceptiontest;

public class Test01 {

    public static void main(String[] args) {
        int m = 10 ; 
        int n = 0 ;
        
        try {
            System.out.println(m/n);
        } catch (Exception e){
            e.printStackTrace();
        }
        
        System.out.println("hello world"); 
    }
    
}

java.lang.ArithmeticException: / by zero
at exceptiontest.Test01.main(Test01.java:10)
hello world

如果使用throws来抛出异常,则hello world不会输出,如

package exceptiontest;

public class Test03 {
    
    public static void main(String args[] ) throws Exception{
        int m = 10;
        int n = 0;
        System.out.println(m/n);
        System.out.println("hello world "); //不会输出
    }
}

 

异常继承结构

Throwable:所有异常都是可以抛出的

Error:java程序运行中如果出现了错误,错误是不能处理的,只能退出JVM,例如StackOverflowError。Error类描述了java运行时系统的内部错误和资源耗尽错误,这种情况很少出现。

Exception是可以处理的,如果没有处理异常,则直接退出JVM

RuntimeException:运行时异常,由程序错误导致的异常属于RuntimeException,而程序本身没问题,但由像I/O错误这类问题导致的异常属于其他异常,或者说编译时异常。可以说,如果出现RuntimeException,那么一定是你的问题,常见的有上面的ArithmeticException,NullPointerException等

编译时异常:Exception所有的直接子类都是编译时异常,如IOException

编译时异常和运行似乎异常

所有的编译时异常,要求程序员在编写程序阶段必须对它进行处理,不处理的话,编译无法通过。有两种处理方式:捕捉(try catch ) 和声明抛出(在方法声明的位置上使用throws关键字抛出异常),出现几率比较高

对于运行时异常,编写程序阶段不需要对其进行处理,出现几率比较低

关于try{}catch{}语句块

 catch{.....}可以写多个,但是必须从上到下,从小(类型异常)到大(类型异常),最多只会执行1个catch{...},之后try{}catch{}语句块就结束了,然后将继续向下执行,throws可以抛出多个异常,用逗号隔开,而且没有大小顺序之分

public class Test02 {

    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("D:/test.txt");//发生异常,
            //try{}中下面得语句将不再执行
            //JVM会自动创建一个FileNotFoundException类型的对象,将该对象的内存地址赋值给catch语句块中的e变量
            System.out.println("rererere");//不会输出
            
            fis.read();
        }catch (FileNotFoundException e){//e内存地址指向堆中那个对象是FileNotFoundException类型的事件
            System.out.println("文件未找到");
            //FileNotFoundException复写了toString方法
            System.out.println(e);
        }catch (IOException e){
            System.out.println("其他IO异常");
        }
        
        System.out.println("hello world");
    }

}

文件未找到
java.io.FileNotFoundException: D:\test.txt (系统找不到指定的文件。)
hello world

关于finally语句块

1.finally可以直接和try语句块联用,如:try{}finally{}

2.finally中的语句是一定会执行的

public class Test04 {

    public static void main(String[] args) {
        try{
            System.out.println("try~");
            return;
        }finally{
            System.out.println("finally~");
        }
    }

}

输出:

try~
finally~

只有一种情况finally语句块不会执行,那就是在finally语句块之前退出了JVM,如

public class Test05 {

    public static void main(String[] args) {
        try{
            System.out.println("before exit....");
            System.exit(0); //退出JVM
            System.out.println("try.....");
        }finally {
            System.out.println("finally....");
        }
    }

}

输出:before exit....

又一个例子

public class Test06 {

    public static void main(String[] args) {
        int  i = fun();
        System.out.println("main..... i = " + i);
    }
    
    public static int fun(){
        int i = 0;
        try{
            i = 10;
            return i;
        }finally {
            i++;
            System.out.println("finally ..... i = " + i);
        }
    }
}

finally ..... i = 11
main..... i = 10

上面try{}中执行原理是这样的

try{
            i = 10;
            int tmp = i;//创建一个临时变量来保存i,并返回这个值
            return tmp;
        }finally {
            i++;   //这里操作的是i而不是tmp
            System.out.println("finally ..... i = " + i);
        }

final、finalize、finally的区别

这几个完全没有关系哈OTZ

1.final修饰的类无法被继承,修饰的方法无法被覆盖,修饰的局部变量一旦赋值不可再改变,修饰的成员变量需要手动赋值,另外,final和static修饰的变量称为常量

2.finalize压根就不是关键字,是Object类里的一个方法的名字,垃圾回收器在回收java对象前会自动调用java调用java对象的finalize方法

3.finally是异常机制中的finally语句块

自定义异常

1.编译时异常,直接继承Exception

2.运行时异常,直接继承RuntimeException

package exceptiontest;

public class Test07 {

    public static void main(String[] args) {
        CustomerService cs = new CustomerService();
        try{
            cs.register("kobe");
        }catch (IllegalNameException e){
            System.out.println(e.getMessage());
        }
        System.out.println("yyyyy");
    }

}

class IllegalNameException extends Exception{
    //定义异常一般提供两个构造方法,嗯 这是套路
    public IllegalNameException(){
        
    }
    
    public IllegalNameException(String msg){
        super(msg);
    }
    
}

class CustomerService{
    public void register(String username) throws IllegalNameException{//里面异常,所有需要throws抛出告诉外面
        
        if (username.length() < 6){
            //创建异常对象,手动抛出,是throw不是throws,用的地方不同啊
            throw new IllegalNameException("用户名长度不能小于6");
        }
        
        System.out.println("注册成功!");
    }
}

用户名长度不能小于6
yyyyy

重写的方法不能比被重写的方法抛出更宽泛的异常

举个栗子

class A{
    public void fun(){
        
    }
}
class B extends A{
    @Override
    public void fun() throws Exception{
        //子类无法抛出比父类更多的异常
        super.fun();
    }
}

以上编译错误:

Exception Exception is not compatible with throws clause in A.fun()

再举个栗子

class A{
    public void fun() throws FileNotFoundException{
        
    }
}
class B extends A{
    @Override
    public void fun() throws IOException{
        //编译错误,子类无法抛出比父类更大(宽)的异常
        super.fun();
    }
}

又一个栗子

class A{
    public void fun() throws IOException{
        
    }
}
class B extends A{
    @Override
    public void fun() throws FileNotFoundException{
        //编译通过
    }
}

 

posted @ 2016-10-02 16:34  Steve_Nash  阅读(239)  评论(0)    收藏  举报