旗下导航:搜·么
当前位置:网站首页 > JAVA教程 > 正文

你必需相识的java中的非常【JAVA教程】,java

作者:搜教程发布时间:2019-11-30分类:JAVA教程浏览:69评论:0


导读:一.异常的定义(引荐:java视频教程)在《java编程头脑》中如许定义异常:阻挠当前要领或作用域继续实行的问题。虽然java中有异常处置惩罚机制,然则要明白一点,...

一. 异常的定义(引荐:java视频教程)

在《java编程头脑》中如许定义 异常:阻挠当前要领或作用域继续实行的问题。虽然java中有异常处置惩罚机制,然则要明白一点,决不应当用"一般"的立场来对待异常。相对一点说异常就是某种意义上的毛病,就是问题,它大概会致使顺序失利。之所以java要提出异常处置惩罚机制,就是要通知开发职员,你的顺序涌现了不一般的状况,请注重。

记得当初进修java的时刻,异常老是搞不太清晰,不知道这个异常是什么意义,为何会有这个机制?然则跟着学问的积聚逐步也对异常有一点认为了。举一个例子来申明一下异常的用处。

public class Calculator {
    public int devide(int num1, int num2) {
        //推断除数是不是为0
        if(num2 == 0) {
            throw new IllegalArgumentException("除数不能为零");
        }
         
        return num1/num2;
    }
}

看一下这个类中关于除运算的要领,如果你是新手你大概会直接返回计算效果,基本不去斟酌什么参数是不是准确,是不是正当(固然能够谅解,谁都是如许过来的)。然则我们应只管的斟酌全面,把大概致使顺序失利的"苗头"抹杀在摇篮中,所以举行参数的正当性搜检就很有必要了。

个中实行参数搜检抛出来的谁人参数不法异常,这就属于这个要领的不一般状况。一般状况下我们会准确的运用计算器,然则不消除粗枝大叶把除数赋值为0。如果你之前没有斟酌到这类状况,而且碰巧用户数学基本不好,那末你完了。然则如果你之前斟酌到了这类状况,那末很显然毛病已在你的掌控当中。

二. 异常扫盲行动

今天和他人聊天时看到一个笑话:世界上最真情的相依,是你在try我在catch。不管你发神马性情,我都默默蒙受,悄悄处置惩罚。 大多数新手对java异常的认为就是:try...catch...。没错,这是用的最多的,也是最有用的。我的认为就是:java异常是从"try...catch..."走来。

起首来熟习一下java的异常系统:

Throwable 类是 Java 言语中一切毛病或异常的超类(这就是统统皆可抛的东西)。它有两个子类:Error和Exception。

Error:用于指导合理的应用顺序不应当试图捕获的严重问题。这类状况是很大的问题,大到你不能处置惩罚了,所以听其自然就好了,你不必管它。比方说VirtualMachineError:当 Java 虚拟机崩溃或用尽了它继续操纵所需的资本时,抛出该毛病。好吧,就算这个异常的存在了,那末应当什么时候,怎样处置惩罚它呢??交给JVM吧,没有比它更专业的了。

Exception:它指出了合理的应用顺序想要捕获的前提。Exception又分为两类:一种是CheckedException,一种是UncheckedException。

这两种Exception的区分主如果CheckedException须要用try...catch...显现的捕获,而UncheckedException不须要捕获。一般UncheckedException又叫做RuntimeException。

我们罕见的RuntimeExcepiton有IllegalArgumentException、IllegalStateException、NullPointerException、IndexOutOfBoundsException等等。关于那些CheckedException就屈指可数了,我们在编写顺序历程当中try...catch...捕获的异常都是CheckedException。io包中的IOException及其子类,这些都是CheckedException。

三. 异常的运用

在异常的运用这一部份主如果演示代码,都是我们寻常写代码的历程当中会碰到的(固然只是一小部份),举一反三吗!

例1. 这个例子重要经由过程两个要领对比来演示一下有了异常今后代码的实行流程。

public static void testException1() {
        int[] ints = new int[] { 1, 2, 3, 4 };
        System.out.println("异常涌现前");
        try {
            System.out.println(ints[4]);
            System.out.println("我还有幸实行到吗");// 发作异常今后,背面的代码不能被实行
        } catch (IndexOutOfBoundsException e) {
            System.out.println("数组越界毛病");
        }
        System.out.println("异常涌现后");
    }
    /*output:
    异常涌现前
    数组越界毛病
    4
    异常涌现后
    */
public static void testException2() {
        int[] ints = new int[] { 1, 2, 3, 4 };
        System.out.println("异常涌现前");
        System.out.println(ints[4]);
        System.out.println("我还有幸实行到吗");// 发作异常今后,他背面的代码不能被实行
    }

起首指出例子中的不足之处,IndexOutofBoundsException是一个非受检异常,所以不必try...catch...显现捕获,然则我的目标是对同一个异常用差别的处置惩罚方式,看它会有什么差别的而效果(这里也就只能用它将就一下了)。异常涌现时第一个要领只是跳出了try块,然则它背面的代码会照样实行的。

然则第二种就不一样了直接跳出了要领,比较倔强。从第一个要领中我们看到,try...catch...是一种"事务性"的保证,它的目标是保证顺序在异常的状况下运转终了,同时它还会示知顺序员顺序中失足的细致信息(这类细致信息偶然要依赖于顺序员设想)。

例2. 从新抛出异常

public class Rethrow {
    public static void readFile(String file) throws FileNotFoundException {
        try {
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.err.println("不知道怎样处置惩罚该异常或许基本不想处置惩罚它,然则不做处置惩罚又不适宜,这是从新抛出异常交给上一级处置惩罚");
            //从新抛出异常
            throw e;
        }
    }
     
    public static void printFile(String file) {
        try {
            readFile(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
     
    public static void main(String[] args) {
        printFile("D:/file");
    }
}

异常的本意是好的,让我们试图修复顺序,然则实际中我们修复的概率很小,我们许多时刻就是用它来纪录失足的信息。如果你厌倦了不断的处置惩罚异常,从新抛出异常对你来讲多是一个很好的摆脱。一成不变的把这个异常抛给上一级,抛给挪用这个要领的人,让他来费头脑吧。如许看来,java异常(固然指的是受检异常)又给我们平增许多贫苦,尽管它的起点是好的。

例3. 异常链的运用及异常丧失

定义三个异常类:ExceptionA,ExceptionB,ExceptionC

public class ExceptionA extends Exception {
    public ExceptionA(String str) {
        super();
    }
}
 
public class ExceptionB extends ExceptionA {
 
    public ExceptionB(String str) {
        super(str);
    }
}
 
public class ExceptionC extends ExceptionA {
    public ExceptionC(String str) {
        super(str);
    }
}

异常丧失的状况:

public class NeverCaught {
    static void f() throws ExceptionB{
        throw new ExceptionB("exception b");
    }
 
    static void g() throws ExceptionC {
        try {
            f();
        } catch (ExceptionB e) {
            ExceptionC c = new ExceptionC("exception a");
            throw c;
        }
    }
 
    public static void main(String[] args) {
            try {
                g();
            } catch (ExceptionC e) {
                e.printStackTrace();
            }
    }
 
}
/*
exception.ExceptionC
at exception.NeverCaught.g(NeverCaught.java:12)
at exception.NeverCaught.main(NeverCaught.java:19)
*/

为何只是打印出来了ExceptionC而没有打印出ExceptionB呢?这个照样本身剖析一下吧!

上面的状况相当于少了一种异常,这在我们排错的历程当中异常的不利。那我们碰到上面的状况应当怎么办呢?这就是异常链的用武之地:保留异常信息,在抛出别的一个异常的同时不丧失本来的异常。

public class NeverCaught {
    static void f() throws ExceptionB{
        throw new ExceptionB("exception b");
    }
 
    static void g() throws ExceptionC {
        try {
            f();
        } catch (ExceptionB e) {
            ExceptionC c = new ExceptionC("exception a");
            //异常连
            c.initCause(e);
            throw c;
        }
    }
 
    public static void main(String[] args) {
            try {
                g();
            } catch (ExceptionC e) {
                e.printStackTrace();
            }
    }
 
}
/*
exception.ExceptionC
at exception.NeverCaught.g(NeverCaught.java:12)
at exception.NeverCaught.main(NeverCaught.java:21)
Caused by: exception.ExceptionB
at exception.NeverCaught.f(NeverCaught.java:5)
at exception.NeverCaught.g(NeverCaught.java:10)
... 1 more
*/

这个异常链的特征是一切异常均具有的,由于这个initCause()要领是从Throwable继续的。

例4. 清算事情

清算事情关于我们来讲是必不可少的,由于如果一些斲丧资本的操纵,比方IO,JDBC。如果我们用完今后没有实时准确的封闭,那效果会很严重,这意味着内存泄漏。异常的涌现请求我们必需设想一种机制不论什么状况下,资本都能实时准确的清算。这就是finally。

public void readFile(String file) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(
                    new FileInputStream(file)));
            // do some other work
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

例子异常的简朴,是一个读取文件的例子。如许的例子在JDBC操纵中也异常的罕见。(所以,我认为关于资本的实时准确清算是一个顺序员的基本素质之一。)

Try...finally组织也是保证资本准确封闭的一个手腕。如果你不清晰代码实行历程当中会发作什么异常状况会致使资本不能获得清算,那末你就用try对这段"可疑"代码举行包装,然后在finally中举行资本的清算。举一个例子:

public void readFile() {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(
                    new FileInputStream("file")));
            // do some other work
         
            //close reader
            reader.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }

我们注重一下这个要领和上一个要领的区分,下一个人大概习气更好一点,尽早的封闭reader。然则每每适得其反,由于在reader.close()之前异常随时大概发作,如许的代码组织不能防备任何异常的涌现。由于顺序会在异常涌现的处所跳出,背面的代码不能实行(这在上面应经用实例证实过)。这时候我们就能够用try...finally来革新:

public void readFile() {
        BufferedReader reader = null;
        try {
            try {
                reader = new BufferedReader(new InputStreamReader(
                        new FileInputStream("file")));
                // do some other work
 
                // close reader
            } finally {
                reader.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

尽早的封闭资本是一种优越的行动,由于时候越长你遗忘封闭的大概性越大。如许在配合上try...finally就保证十拿九稳了(不要嫌贫苦,java就是这么中规中矩)。

再说一种状况,如果我想在组织要领中翻开一个文件或许建立一个JDBC衔接,由于我们要在其他的要领中运用这个资本,所以不能在组织要领中尽早的将这个资本封闭。那我们是不是是就没辙了呢?答案是不是定的。看一下下面的例子:

public class ResourceInConstructor {
    BufferedReader reader = null;
    public ResourceInConstructor() {
        try {
            reader = new BufferedReader(new InputStreamReader(new FileInputStream("")));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
     
    public void readFile() {
        try {
            while(reader.readLine()!=null) {
                //do some work
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
     
    public void dispose() {
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这一部份讲的多了一点,然则异常确切是看起来轻易用起来难的东西呀,java中照样有很多的东西须要深挖的。

四. 异常的误用

关于异常的误用实在很罕见,上一部份中已列举了几个,人人细致的看一下。下面再说两个其他的。

例1. 用一个Exception来捕获一切的异常,很有"一夫当关万夫莫开"的气势。不过这也是最傻的行动。

public void readFile(String file) {
        BufferedReader reader = null;
        Connection conn = null;
        try {
            reader = new BufferedReader(new InputStreamReader(
                    new FileInputStream(file)));
            // do some other work
             
            conn = DriverManager.getConnection("");
            //...
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

从异常角度来讲如许严厉的顺序确切是十拿九稳,一切的异常都能捕获。然则站在编程职员的角度,万一这个顺序失足了我们该怎样区分是究竟是那引发的呢,IO照样JDBC...所以,这类写法很值得当作一个反例。人人不要认为这类做法很稚子,傻子才会做。我在公司练习时确切看见了相似的状况:只不过是人家没有用Exception而是用了Throwable。

例2. 这里就不举例子了,上面的顺序都是反例。异常是顺序处置惩罚不测状况的机制,当顺序发作不测时,我们须要只管多的获得不测的信息,包含发作的位置,形貌,缘由等等。

这些都是我们解决问题的线索。然则上面的例子都只是简朴的printStackTrace()。如果我们本身写代码,就要只管多的对这个异常举行形貌。比方说为何会涌现这个异常,什么状况下会发作这个异常。如果传入要领的参数不准确,示知什么样的参数是正当的参数,或许给出一个sample。

例3. 将try block写的简短,不要一切的东西都扔在这里,我们只管的剖析出究竟哪几行顺序大概涌现异常,只是对大概涌现异常的代码举行try。只管为每个异常写一个try...catch,防止异常丧失。

更多java学问请关注java基本教程栏目。

以上就是你必需相识的java中的异常的细致内容,更多请关注ki4网别的相干文章!

标签:java


欢迎 发表评论: