1. 예외의 종류

모든 예외는 실제로 서로 상속하는 클래스인 4가지 유형으로 나뉩니다.

Throwable수업

모든 예외의 기본 클래스는 클래스입니다 Throwable. Throwable클래스에는 현재 호출 스택(현재 메서드의 스택 추적)을 배열에 쓰는 코드가 포함되어 있습니다. 스택 추적이 무엇인지 잠시 후에 배우겠습니다.

throw 연산자 는 클래스 에서 파생된 개체만 허용할 수 있습니다 Throwable. 그리고 이론적으로 와 같은 코드를 작성할 수 있지만 throw new Throwable();일반적으로 아무도 이렇게 하지 않습니다. 클래스 의 주요 목적은 Throwable모든 예외에 대해 단일 부모 클래스를 갖는 것입니다.

Error수업

다음 예외 클래스는 클래스를 Error직접 상속하는 클래스 입니다 Throwable. Java 머신은 심각한 문제가 발생했을 때Error 클래스(및 그 자손) 의 객체를 생성합니다 . 예를 들어 하드웨어 오작동, 메모리 부족 등이 있습니다.

일반적으로 프로그래머는 프로그램에서 이러한 오류(an이 발생해야 하는 종류)가 발생한 상황에서 할 수 있는 일이 없습니다 . 이러한 오류는 너무 심각합니다. Error할 수 있는 일은 프로그램이 충돌하고 있음을 사용자에게 알리거나 프로그램 로그에 오류에 대한 모든 알려진 정보를 기록하는 것뿐입니다.

Exception수업

및 클래스 ExceptionRuntimeException많은 메서드 작업에서 발생하는 일반적인 오류를 위한 것입니다. 발생한 각 예외의 목표는 적절하게 처리하는 방법을 알고 있는 블록 에 의해 포착되는 것입니다 .catch

메소드가 어떤 이유로 작업을 완료할 수 없는 경우 적절한 유형의 예외를 발생시켜 호출 메소드에 즉시 알려야 합니다.

즉, 변수가 와 같으면 null메소드는 를 발생시킵니다 NullPointerException. 잘못된 인수가 메서드에 전달된 경우 InvalidArgumentException. 메서드가 실수로 0으로 나누면 ArithmeticException.

RuntimeException수업

RuntimeExceptions의 하위 집합입니다 Exceptions. RuntimeException일반적인 예외( )의 경량 버전이라고 말할 수도 있습니다 Exception. 이러한 예외에 대한 요구 사항과 제한이 적습니다.

Exception과 의 차이점은 나중에 배우게 됩니다 RuntimeException.


2. Throws: 확인된 예외

모든 Java 예외는 2가지 범주로 나뉩니다: checkedunchecked .

RuntimeException또는 를 상속하는 모든 예외는 확인되지 않은 예외로Error 간주됩니다 . 다른 모든 것은 확인된 예외 입니다 .

중요한!

확인된 예외가 도입된 지 20년이 지난 지금 거의 모든 Java 프로그래머는 이를 버그로 생각합니다. 인기 있는 최신 프레임워크에서는 모든 예외의 95%가 확인되지 않습니다. Java를 거의 그대로 복사한 C# 언어는 확인된 예외를 추가하지 않았습니다 .

확인된 예외 와 확인되지 않은 예외 의 주요 차이점은 무엇입니까 ?

확인된 예외 에 부과되는 추가 요구 사항이 있습니다 . 대략적으로 말하면 다음과 같습니다.

요건 1

메서드가 확인된 예외를 throw 하는 경우 서명에 예외 유형을 나타내야 합니다 . 그런 식으로 이를 호출하는 모든 메서드는 이 "의미 있는 예외"가 발생할 수 있음을 인식합니다.

키워드 뒤의 메서드 매개변수 뒤에 확인된 예외를 나타냅니다 ( 키워드를 실수로 사용하지 마십시오 ). 다음과 같이 보입니다.throwsthrow

type method (parameters) throws exception

예:

확인된 예외 확인되지 않은 예외
public void calculate(int n) throws Exception
{
   if (n == 0)
      throw new Exception("n is null!");
}
public void calculate(n)
{
   if (n == 0)
      throw new RuntimeException("n is null!");
}

오른쪽 예에서 코드는 확인되지 않은 예외를 발생시킵니다. 추가 조치가 필요하지 않습니다. 왼쪽의 예에서 메서드는 확인된 예외를 throw하므로 throws예외 유형과 함께 키워드가 메서드 시그니처에 추가됩니다.

메서드가 여러 확인된 예외를 throw할 것으로 예상되는 경우 모두 throws키워드 뒤에 쉼표로 구분하여 지정해야 합니다. 순서는 중요하지 않습니다. 예:

public void calculate(int n) throws Exception, IOException
{
   if (n == 0)
      throw new Exception("n is null!");
   if (n == 1)
      throw new IOException("n is 1");
}

요건 2

서명에서 예외를 확인한 메서드를 호출하면 예외가 발생한다는 사실을 무시할 수 없습니다.

catch각각에 대한 블록을 추가하거나 메서드의 에 추가 하여 이러한 모든 예외를 catch해야 합니다.throws

" 이러한 예외는 매우 중요하므로 반드시 잡아야 합니다. 그리고 우리가 이를 처리하는 방법을 모른다면 우리 메서드를 호출할 수 있는 모든 사람에게 그러한 예외가 발생할 수 있음을 알려야 합니다.

예:

인간이 거주하는 세상을 만드는 방법을 작성한다고 상상해보십시오. 초기 인원수는 인수로 전달됩니다. 따라서 사람이 너무 적으면 예외를 추가해야 합니다.

지구 만들기 메모
public void createWorld(int n) throws EmptyWorldException, LonelyWorldException
{
   if (n == 0)
      throw new EmptyWorldException("There are no people!");
   if (n == 1)
      throw new LonelyWorldException ("There aren't enough people!");
   System.out.println("A wonderful world was created. Population: " + n);
}
이 메서드는 잠재적으로 두 가지 확인된 예외를 throw합니다.

  • EmptyWorldException
  • LonelyWorldException

이 메서드 호출은 3가지 방법으로 처리할 수 있습니다.

1. 예외를 잡지 않는다

이는 메서드가 상황을 적절하게 처리하는 방법을 모를 때 가장 자주 수행됩니다.

암호 메모
public void createPopulatedWorld(int population)
throws EmptyWorldException, LonelyWorldException
{
   createWorld(population);
}
호출 메서드는 예외를 포착하지 않으며 예외에 대해 다른 사람에게 알려야 합니다. 자신의 throws절 에 예외를 추가합니다.

2. 일부 예외를 잡아라

우리는 우리가 처리할 수 있는 오류를 처리합니다. 그러나 우리가 이해하지 못하는 것들은 호출 메서드에 던집니다. 이렇게 하려면 throws 절에 이름을 추가해야 합니다.

암호 메모
public void createNonEmptyWorld(int population)
throws EmptyWorldException
{
   try
   {
      createWorld(population);
   }
   catch (LonelyWorldException e)
   {
      e.printStackTrace();
   }
}
호출자는 하나 의 확인된 예외( ) 만 포착합니다 LonelyWorldException. 다른 예외는 서명에 추가해야 하며 키워드 뒤에 표시해야 합니다 throws.

3. 모든 예외를 잡아라

메서드가 호출 메서드에 대한 예외를 throw하지 않으면 호출 메서드는 항상 모든 것이 잘 작동한다고 확신합니다. 그리고 예외적인 상황을 해결하기 위해 어떤 조치도 취할 수 없습니다.

암호 메모
public void createAnyWorld(int population)
{
   try
   {
      createWorld(population);
   }
   catch (LonelyWorldException e)
   {
      e.printStackTrace();
   }
   catch (EmptyWorldException e)
   {
      e.printStackTrace();
   }
}
모든 예외는 이 메서드에서 포착됩니다. 발신자는 모든 것이 잘 되었다고 확신할 것입니다.


3. 여러 예외 잡기

프로그래머는 코드 복제를 정말 싫어합니다. 그들은 심지어 상응하는 개발 원칙인 DRY : 반복하지 마십시오. 그러나 예외를 처리할 때 한 블록 다음에 동일한 코드를 가진 여러 블록이 오는 경우가 자주 있습니다 .trycatch

catch또는 동일한 코드를 가진 3개의 블록과 다른 동일한 코드를 가진 또 다른 2개의 블록이 있을 수 있습니다 catch. 이것은 프로젝트가 책임감 있게 예외를 처리하는 표준 상황입니다.

버전 7부터 Java 언어에서 단일 catch블록에 여러 유형의 예외를 지정하는 기능이 추가되었습니다. 대략 다음과 같습니다.

try
{
   // Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
   // Exception handling code
}

catch원하는 만큼 블록을 가질 수 있습니다 . 그러나 단일 catch블록은 서로 상속되는 예외를 지정할 수 없습니다. 즉 , Exception클래스 RuntimeException가 .RuntimeExceptionException