> Java > java지도 시간 > 본문

Java 개선(17)------예외(2)

黄舟
풀어 주다: 2017-02-10 11:45:30
원래의
1040명이 탐색했습니다.

이전 블로그 게시물에 이어서: Java 개선 장(16)------예외(1)

5. 사용자 정의 예외

 Java는 많은 예외를 제공하지만 예외 시스템은 우리가 보고하려는 모든 오류를 예측할 수 없으므로 Java를 통해 예외를 사용자 정의할 수 있습니다. 즉, 프로그램에서 발생할 수 있는 특정 문제를 나타냅니다. 즉, Java의 기존 예외 유형을 고수할 필요가 없습니다.

 Java 사용자 정의 예외를 사용하려면 다음 네 단계가 필요합니다.

  1. Throwable 또는 해당 하위 클래스를 상속할 클래스를 정의합니다.

  2. 공법 추가 (물론 추가하지 않고 기본 공법을 그대로 사용할 수도 있습니다. 그것).

         3. 이 예외를 특정 메소드 클래스에 발생시킵니다.

  4. 예외를 포착합니다.

아아앙

 실행 결과:


>

여러 객체를 하나의 체인으로 연결하는 책임 체인 패턴이라는 디자인 패턴이 있습니다. 클라이언트의 요청은 수신되어 처리될 때까지 이 체인을 따라 전달됩니다. 마찬가지로 Java 예외 메커니즘도 예외 체인과 같은 체인을 제공합니다.

              우리는 예외 메시지가 나타날 때마다 시도해야 한다는 것을 알고 있습니다. 하나는 괜찮습니다. 여러 예외가 발생하면 어떻게 되나요? 분류 처리는 확실히 더 번거로울 것이므로 하나의 Exception을 사용하여 모든 예외를 해결하십시오. 이는 실제로 가능하지만 이 접근 방식은 필연적으로 후속 유지 관리를 더욱 어렵게 만듭니다. 가장 좋은 방법은 이러한 예외 정보를 캡슐화한 다음 캡슐화 클래스를 캡처하는 것입니다.

애플리케이션에서 때로는 예외를 캡슐화해야 할 뿐만 아니라 전달하세요. 배달하는 방법? 던진다! 폭식, 맞아! ! 하지만 단지 throw를 사용하여 예외를 발생시키는 경우 캡슐화된 클래스로 무엇을 해야 할까요? ?

예외를 처리하는 방법에는 두 가지가 있습니다. 하나는 처리를 위해 상위에 전달하는 것입니다. 다른 하나는 try...catch가 특정 처리를 수행하는 것입니다. 그러나 이것이 위의 내용과 어떤 관련이 있습니까? try...catch의 catch 블록에서는 어떤 처리도 할 필요가 없습니다. 단지 throw 키워드를 사용하여 캡슐화한 예외 정보를 적극적으로 던지기만 하면 됩니다. 그런 다음 키워드 throw를 통해 메소드 예외를 계속 발생시킵니다. 상위 계층에서도 이러한 처리를 수행할 수 있으며, 비유하자면 예외로 구성된 예외 체인이 생성됩니다.

                                          시스템 친화성.

      同理,我们有时候在捕获一个异常后抛出另一个异常信息,并且希望将原始的异常信息也保持起来,这个时候也需要使用异常链。

      在异常链的使用中,throw抛出的是一个新的异常信息,这样势必会导致原有的异常信息丢失,如何保持?在Throwable及其子类中的构造器中都可以接受一个cause参数,该参数保存了原有的异常信息,通过getCause()就可以获取该原始异常信息。

      语法:

public void test() throws XxxException{
        try {
            //do something:可能抛出异常信息的代码块
        } catch (Exception e) {
            throw new XxxException(e);
        }
    }
로그인 후 복사

示例:

public class Test {
    public void f() throws MyException{
         try {
            FileReader reader = new FileReader("G:\\myfile\\struts.txt");  
             Scanner in = new Scanner(reader);  
             System.out.println(in.next());
        } catch (FileNotFoundException e) {
            //e 保存异常信息
            throw new MyException("文件没有找到--01",e);
        }  
    }
    
    public void g() throws MyException{
        try {
            f();
        } catch (MyException e) {
            //e 保存异常信息
            throw new MyException("文件没有找到--02",e);
        }
    }
    
    public static void main(String[] args) {
        Test t = new Test();
        try {
            t.g();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
}
로그인 후 복사


运行结果:

com.test9.MyException: 文件没有找到--02
    at com.test9.Test.g(Test.java:31)
    at com.test9.Test.main(Test.java:38)
Caused by: com.test9.MyException: 文件没有找到--01
    at com.test9.Test.f(Test.java:22)
    at com.test9.Test.g(Test.java:28)
    ... 1 more
Caused by: java.io.FileNotFoundException: G:\myfile\struts.txt (系统找不到指定的路径。)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:106)
    at java.io.FileInputStream.<init>(FileInputStream.java:66)
    at java.io.FileReader.<init>(FileReader.java:41)
    at com.test9.Test.f(Test.java:17)
    ... 2 more
로그인 후 복사

如果在程序中,去掉e,也就是:throw new MyException("文件没有找到--02");

那么异常信息就保存不了,运行结果如下:

com.test9.MyException: 文件没有找到--02
    at com.test9.Test.g(Test.java:31)
    at com.test9.Test.main(Test.java:38)
로그인 후 복사

PS:其实对于异常链鄙人使用的也不是很多,理解的不是很清楚,望各位指正!!!!

七、异常的使用误区

首先我们先看如下示例:该实例能够反映java异常的不正确使用(其实这也是我刚刚学Java时写的代码)!!

OutputStreamWriter out = null;
        java.sql.Connection conn = null;
        try {            //   ---------1
            Statement stat = conn.createStatement();
            ResultSet rs = stat.executeQuery("select *from user");
            while (rs.next()){
                out.println("name:" + rs.getString("name") + "sex:"
                        + rs.getString("sex"));
            }
            conn.close();         //------2
            out.close();
        } 
        catch (Exception ex){    //------3
            ex.printStackTrace();    //------4
        }
로그인 후 복사


1、-----------1

对于这个try…catch块,我想他的真正目的是捕获SQL的异常,但是这个try块是不是包含了太多的信息了。这是我们为了偷懒而养成的代码坏习惯。有些人喜欢将一大块的代码全部包含在一个try块里面,因为这样省事,反正有异常它就会抛出,而不愿意花时间来分析这个大代码块有那几块会产生异常,产生什么类型的异常,反正就是一篓子全部搞定。这就想我们出去旅游将所有的东西全部装进一个箱子里面,而不是分类来装,虽不知装进去容易,找出来难啊!!!所有对于一个异常块,我们应该仔细分清楚每块的抛出异常,因为一个大代码块有太多的地方会出现异常了。

结论一:尽可能的减小try块!!!

2、--------2

 여기서 무엇을 찾았나요? 예외는 실행 중인 프로세스를 변경합니다! ! 좋은 점은 예외가 프로그램의 실행 흐름을 변경한다는 것입니다. 프로그램에서 예외가 발생하면 conn.close();out.close();를 실행할 수 없으며, 이로 인해 필연적으로 리소스가 해제되지 않습니다. 따라서 프로그램이 파일, 소켓, JDBC 연결 등의 자원을 사용하는 경우 예외가 발생하더라도 점유된 자원이 올바르게 해제될 수 있는지 확인해야 합니다. 이것이 마침내 등장하는 곳입니다. 예외 발생 여부에 관계없이 마침내 항상 실행할 기회가 있으므로 finally는 리소스를 해제하는 데 적합합니다.

 결론 2: 모든 리소스가 올바르게 해제되었는지 확인하세요. finally 키워드를 최대한 활용하세요.

 3. ----------3

 이 코드의 경우 대부분의 사람들이 이런 식으로 대처한다고 생각합니다(LZ도 마찬가지). 이러한 코드를 사용하는 사람들은 한 번만 잡으면 모든 예외가 해결될 수 있다는 사고방식을 가지고 있습니다. 이는 가능하지만 권장되지는 않습니다. 왜! 우선, catch 블록이 어떤 종류의 예외가 발생할 것으로 예상되는지, 어떤 종류의 처리를 수행해야 하는지를 나타내는 것을 이해해야 합니다. Exception을 사용한다는 것은 모든 예외 정보를 처리해야 한다는 의미이지만 수행한다는 의미는 무엇입니까? 그래서?

여기서 위의 프로그램 예를 다시 살펴보겠습니다. throw 두 가지 예외 정보, SQLException 및 IOException. 따라서 한 번의 catch로 두 개의 완전히 다른 예외를 처리하는 것은 분명히 부적절합니다. 두 개의 catch(SQLException을 처리하는 데 하나, IOException을 처리하는 데 하나)를 사용하면 훨씬 더 좋습니다. 따라서:

 결론 3: catch 문은 다음과 같아야 합니다. 가능한 예외 유형을 구체적으로 지정해야 하며 너무 넓은 범위를 포괄하는 Exception 클래스를 지정해서는 안 됩니다. 하나의 예외로 가능한 모든 예외를 처리하려고 하지 마십시오.

 4, --- -------4

 이것이 바로 문제가 너무 많아서 거의 모든 사람이 이런 식으로 사용했다고 확신할 수 있습니다. 여기에는 두 가지 문제가 있습니다. 하나는 예외가 발생했지만 처리되지 않는다는 것이고, 다른 하나는 예외 정보가 충분히 명확하지 않다는 것입니다.

                                                              ~ 예외는 프로그램에 예상치 못한 문제가 발생했음을 의미한다는 것을 우리는 모두 알고 있습니다. 프로그램은 이를 처리하여 이를 저장할 수 있기를 바라지만 여러분은 어떻습니까? ex.printStackTrace() 한 문장이면 충분합니다. 프로그램의 비정상적인 상황을 무시하는 것은 얼마나 무책임한 일입니까? 디버깅 중에는 도움이 될 수 있지만 디버깅 단계가 끝난 후에는 어떻게 되나요? ex.printStackTrace()만으로는 모든 것을 할 수 없습니다!

 그럼 어떻게 개선해야 할까요? 네 가지 옵션이 있습니다.

  1. 예외를 처리합니다. 오류 수정, 알림 제공 등 발생하는 예외를 처리합니다. 다시 말하지만, ex.printStackTrace()는 "예외를 처리"한 것으로 간주되지 않습니다.

2、重新抛出异常。既然你认为你没有能力处理该异常,那么你就尽情向上抛吧!!!

3、封装异常。这是LZ认为最好的处理方法,对异常信息进行分类,然后进行封装处理。

4、不要捕获异常。

4.2、异常信息不明确。我想对于这样的:java.io.FileNotFoundException: ………信息除了我们IT人没有几个人看得懂和想看吧!所以在出现异常后,我们最好能够提供一些文字信息,例如当前正在执行的类、方法和其他状态信息,包括以一种更适合阅读的方式整理和组织printStackTrace提供的信息。起码我公司是需要将异常信息所在的类、方法、何种异常都需要记录在日志文件中的。

所以:

结论四:既然捕获了异常,就要对它进行适当的处理。不要捕获异常之后又把它丢弃,不予理睬。 不要做一个不负责的人。

结论五:在异常处理模块中提供适量的错误原因信息,组织错误信息使其易于理解和阅读。

对于异常还有以下几个注意地方:

六、不要在finally块中处理返回值。

七、不要在构造函数中抛出异常。



八、try…catch、throw、throws

在这里主要是区分throw和throws。

throws是方法抛出异常。在方法声明中,如果添加了throws子句,表示该方法即将抛出异常,异常的处理交由它的调用者,至于调用者任何处理则不是它的责任范围内的了。所以如果一个方法会有异常发生时,但是又不想处理或者没有能力处理,就使用throws吧!

而throw是语句抛出异常。它不可以单独使用,要么与try…catch配套使用,要么与throws配套使用。

//使用throws抛出异常
    public void f() throws MyException{
         try {
            FileReader reader = new FileReader("G:\\myfile\\struts.txt");  
             Scanner in = new Scanner(reader);  
             System.out.println(in.next());
        } catch (FileNotFoundException e) {
            throw new MyException("文件没有找到", e);    //throw
        }  
        
    }
로그인 후 복사




 9. 요약

 실제로 예외 사용의 장점과 단점에 대해 많은 논의가 있습니다. 예: http://www.php.cn/. 이 블로그 게시물에서는 예외 사용 여부에 대해 더 심층적으로 논의합니다. LZ는 정말 신인이라 지극히 심오한 내용을 이해하지 못합니다. 하지만 LZ가 확신할 수 있는 것 중 하나는 이상이 발생하면 시스템 성능에 반드시 영향을 미칠 것이라는 점입니다.

예외 사용 가이드(발췌: Think in java)

다음과 같은 경우에는 예외를 사용해야 합니다.

  1. 적절한 수준에서 문제를 처리합니다(처리 방법을 알고 있는 경우에만 예외를 포착합니다). 비정상입니다).

2. 문제를 해결하고 예외가 발생한 메서드를 다시 호출합니다.

  3. 약간의 패치를 한 후 예외가 발생한 곳을 우회하여 계속 실행합니다.

  4. 다른 데이터를 사용하여 계산을 수행하여 메서드에서 반환될 것으로 예상되는 값을 바꿉니다.

  5. 현재 운영 환경에서 할 수 있는 모든 것을 해보세요. 그런 다음 동일한(다른) 예외가 더 높은 수준으로 다시 발생합니다.

  6. 프로그램을 종료합니다.

  7. 단순화하세요.

   8. 수업 라이브러리와 프로그램을 더욱 안전하게 만듭니다. (디버깅을 위한 단기 투자이자 프로그램의 견고성을 위한 장기 투자입니다)


위 내용은 Java 개선 장(17)의 내용입니다.------예외(2)에 대한 내용을 참조하시기 바랍니다. PHP 중국어 웹사이트(www.php.cn)를 주목하세요!


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿