>  기사  >  Java  >  Java의 예외 처리: 전체 가이드

Java의 예외 처리: 전체 가이드

Susan Sarandon
Susan Sarandon원래의
2024-11-06 07:17:02890검색

Gestion des Exceptions en Java : Guide Complet

Java의 예외는 강력한 프로그래밍의 중요한 부분입니다. 실제로 오류를 체계적이고 예측 가능한 방식으로 관리할 수 있습니다. 이 문서에서는 Java의 예외 처리 시스템을 심층적으로 살펴보고, 모범 사례를 제공하고, 다루는 개념을 설명하는 실제 사례를 포함합니다.

1. 예외 소개

Java에서 예외는 프로그램 실행 중에 발생하여 정상적인 명령 흐름을 방해하는 예상치 못한 이벤트입니다. 예외를 사용하면 프로그램이 충돌 없이 오류를 처리할 수 있습니다.

간단한 오류 예: 0으로 나누기:

public class DivisionParZero {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        System.out.println(a / b);  // Lève une ArithmeticException
    }
}

2. Java의 예외 유형

Java는 예외를 세 가지 주요 범주로 분류합니다.

2.1. 확인된 예외

이러한 예외는 throw를 사용하여 메서드 시그니처에서 포착하거나 선언해야 합니다. 파일 액세스나 네트워크 연결과 같은 외부 이벤트로 인해 발생하는 경우가 많습니다.

  • IOException: 입출력 작업이 실패할 때 발생합니다. 예를 들어 존재하지 않는 파일에 액세스하는 경우(FileNotFoundException).
  • SQLException: 데이터베이스 조작 오류 중에 발생합니다.
  • ClassNotFoundException: JVM이 지정된 클래스를 찾을 수 없을 때 발생하는 예외입니다.
  • InstantiationException: 추상 클래스 또는 인터페이스를 인스턴스화하려고 시도하는 경우.
  • InterruptedException: 대기 중인 스레드가 중단될 때 발생합니다.
  • ParseException: 데이터, 특히 날짜를 구문 분석할 때 오류로 인해 발생합니다.

2.2. 확인되지 않은 예외

확인되지 않은 예외는 RuntimeException에서 상속되며 포착하거나 선언할 필요가 없습니다. 프로그래밍 오류로 인해 발생하는 경우가 많습니다.

  • NullPointerException: Null 참조를 사용하려고 시도했습니다.
  • ArrayIndexOutOfBoundsException: 잘못된 배열 인덱스에 액세스합니다.
  • ArithmeticException: 0으로 나누기와 같은 수학 연산이 잘못되었습니다.
  • IllegalArgumentException: 메서드에 부적절한 인수를 사용했습니다.
  • NumberFormatException: 숫자가 아닌 문자열을 숫자로 변환(예: Integer.parseInt("abc")).
  • IllegalStateException: 객체의 부적절한 상태에서 메서드를 호출합니다.

2.3. 오류

Java 오류는 일반적으로 프로그램이 처리할 수 없는 심각한 시스템 관련 문제입니다.

  • OutOfMemoryError: JVM의 메모리가 부족할 때 발생합니다.
  • StackOverflowError: 과도한 재귀가 스택 크기를 초과하는 경우 발생합니다.
  • VirtualMachineError: InternalError 및 UnknownError와 같은 중요한 JVM 오류에 대한 상위 클래스입니다.
  • AssertionError: 어설션 실패로 인해 발생한 오류입니다.

기타 알려진 특정 예외

  • StringIndexOutOfBoundsException: 문자열에서 범위를 벗어난 문자 위치에 액세스하려고 시도하는 경우.
  • ClassCastException: 객체를 호환되지 않는 유형으로 캐스팅하려고 시도했습니다.
  • UnsupportedOperationException: 현재 구현에서 지원되지 않는 작업을 호출합니다.
  • ConcurrentModificationException: 반복 중 컬렉션 수정

이러한 예외는 Java에서 발생할 수 있는 광범위한 오류를 다루며 애플리케이션 내에서 다양한 오류 시나리오를 처리하기 위한 포괄적인 기반을 제공합니다.

3. 예외 처리

Java에서 예외 처리는 주로 try, catch, finally 및 throw 블록에 의존합니다. 사용에 대한 자세한 개요는 다음과 같습니다.

블록을 시도하고 잡아라

try 블록은 예외를 생성할 수 있는 코드를 캡슐화합니다. 예외가 발생하면 해당 catch 블록이 실행되어 이 예외를 포착하고 처리하여 프로그램 충돌을 방지합니다.

예:
문자열을 정수로 변환하고 싶지만 문자열이 유효한 숫자가 아닐 수도 있는 시나리오를 상상해 봅시다.

public class DivisionParZero {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        System.out.println(a / b);  // Lève une ArithmeticException
    }
}

이 예에서는 사용자가 "abc"와 같이 정수로 변환할 수 없는 문자열을 입력하면 catch 블록이 NumberFormatException을 포착하고 오류 메시지를 표시하므로 프로그램 중단을 방지할 수 있습니다.

마침내 차단하다

예외 발생 여부에 관계없이 finally 블록은 try 및 catch 블록 이후에 실행됩니다. 리소스를 항상 적절하게 정리하기 위해 리소스를 확보하는 데(예: 파일 또는 네트워크 연결 닫기) 사용되는 경우가 많습니다.

예:

public class GestionDesExceptions {
    public static void main(String[] args) {
        try {
            int number = Integer.parseInt("abc"); // Provoquera une NumberFormatException
        } catch (NumberFormatException e) {
            System.out.println("Erreur : la chaîne de caractères n'est pas un nombre valide.");
        }
    }
}

여기서 finally 블록은 파일 발견 여부에 관계없이 파일을 닫아 리소스를 해제합니다.

키워드 던지기

throw 키워드는 명시적으로 예외를 발생시키는 데 사용됩니다. 이는 코드의 특정 유효성 검사에 유용할 수 있습니다.

예:

public class GestionDesExceptions {
    public static void main(String[] args) {
        FileReader fr = null;
        try {
            fr = new FileReader("fichier.txt");
            // Lire le fichier
        } catch (FileNotFoundException e) {
            System.out.println("Erreur : fichier non trouvé.");
        } finally {
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    System.out.println("Erreur lors de la fermeture du fichier.");
                }
            }
        }
    }
}

이 예에서 나이가 음수인 경우 throw는 IllegalArgumentException을 명시적으로 발생시켜 논리적 오류를 나타냅니다.

4. 예외 전파

때때로 예외를 즉시 포착하는 것보다 전파하는 것이 더 나을 때도 있습니다. 특히 현재 메서드가 예외를 제대로 처리할 수 없는 경우에는 더욱 그렇습니다. 이는 메서드 선언의 throws 키워드를 사용하여 수행됩니다.

예:

public class GestionDesExceptions {
    public static void main(String[] args) {
        try {
            validerAge(-5); 
        } catch (IllegalArgumentException e) {
            System.out.println("Erreur : " + e.getMessage());
        }
    }

    public static void validerAge(int age) {
        if (age < 0) {
            throw new IllegalArgumentException("L'âge ne peut pas être négatif.");
        }
    }
}

여기서 openFile은 throws IOException을 사용합니다. 이는 호출자가 예외를 처리할 수 있음을 의미합니다. FileReader가 파일을 찾을 수 없으면 FileNotFoundException이 발생하고 기본 메서드의 catch 블록에 전달됩니다.

이 전파는 사용자에게 오류 메시지를 표시하기 위해 프레젠테이션 계층과 같이 호출 계층 구조에서 더 높은 수준의 예외를 처리해야 하는 더 복잡한 아키텍처에 유용합니다.

5. 사용자 정의 예외

Java를 사용하면 Exception 또는 RuntimeException 클래스에서 상속하여 사용자 정의 예외를 생성할 수 있습니다. 이러한 예외는 표준 예외에서 다루지 않는 애플리케이션별 오류를 보고하는 데 유용합니다.

사용자 정의 예외 예

사용자가 보유한 금액보다 더 많은 금액을 인출할 수 없는 은행 앱을 만든다고 가정해 보겠습니다. InsufficientBalanceException을 생성하겠습니다.

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class PropagationException {
    public static void main(String[] args) {
        try {
            ouvrirFichier("fichier_inexistant.txt");
        } catch (IOException e) {
            System.out.println("Erreur lors de l'ouverture du fichier : " + e.getMessage());
        }
    }

    public static void ouvrirFichier(String nomFichier) throws IOException {
        FileReader lecteur = new FileReader(nomFichier); // Peut lever FileNotFoundException
        lecteur.close();
    }
}

그런 다음 이를 메인 프로그램에서 사용하여 잔액이 부족한 상황을 처리합니다.

public class SoldeInsuffisantException extends Exception {
    public SoldeInsuffisantException(String message) {
        super(message);
    }
}

이 예에서 InsufficientBalanceException은 인출할 금액이 사용 가능한 잔액을 초과함을 나타내는 사용자 정의 예외입니다. 이 오류를 처리하면 명시적인 오류 메시지가 제공되어 코드 가독성과 유지 관리성이 향상됩니다.

사용자 검증을 위한 사용자 정의 예외의 예

나이가 18세에서 65세 사이여야 하는 사용자 검증 시스템을 상상해 보겠습니다. AgeInvalideException을 생성할 수 있습니다.

public class DivisionParZero {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        System.out.println(a / b);  // Lève une ArithmeticException
    }
}

사용법:

public class GestionDesExceptions {
    public static void main(String[] args) {
        try {
            int number = Integer.parseInt("abc"); // Provoquera une NumberFormatException
        } catch (NumberFormatException e) {
            System.out.println("Erreur : la chaîne de caractères n'est pas un nombre valide.");
        }
    }
}

여기서 나이가 조건을 충족하지 않으면 AgeInvalideException이 발생합니다. 이 사용자 정의 예외는 정확한 유효성 검사와 명확한 오류 메시지를 제공하여 사용자 경험을 향상시킵니다.

try, catch, finally 및 사용자 정의 예외를 통한 Java의 예외 처리를 통해 세부적인 오류 제어, 코드 가독성 향상, 전문 애플리케이션에서의 사용자 경험 향상이 가능합니다.

6. 예외 처리 모범 사례

6.1 의미 있는 예외 사용

원칙: 오류에 대한 정확한 컨텍스트를 제공하려면 예외 메시지가 명시적이어야 합니다.

나쁜 습관:

public class GestionDesExceptions {
    public static void main(String[] args) {
        FileReader fr = null;
        try {
            fr = new FileReader("fichier.txt");
            // Lire le fichier
        } catch (FileNotFoundException e) {
            System.out.println("Erreur : fichier non trouvé.");
        } finally {
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    System.out.println("Erreur lors de la fermeture du fichier.");
                }
            }
        }
    }
}

개선:
특정 예외와 명확한 메시지를 사용하고, 일반적인 도메인별 오류를 반영하는 경우 사용자 정의 예외를 생성하는 것을 선호합니다.

public class GestionDesExceptions {
    public static void main(String[] args) {
        try {
            validerAge(-5); 
        } catch (IllegalArgumentException e) {
            System.out.println("Erreur : " + e.getMessage());
        }
    }

    public static void validerAge(int age) {
        if (age < 0) {
            throw new IllegalArgumentException("L'âge ne peut pas être négatif.");
        }
    }
}

6.2 흐름 제어에 대한 예외 방지

예외는 if-else와 같은 제어 구조를 재정의해서는 안 됩니다. 이러한 방식으로 예외를 사용하면 성능 측면에서 비용이 많이 들고 코드 읽기가 어려워집니다.

나쁜 습관:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class PropagationException {
    public static void main(String[] args) {
        try {
            ouvrirFichier("fichier_inexistant.txt");
        } catch (IOException e) {
            System.out.println("Erreur lors de l'ouverture du fichier : " + e.getMessage());
        }
    }

    public static void ouvrirFichier(String nomFichier) throws IOException {
        FileReader lecteur = new FileReader(nomFichier); // Peut lever FileNotFoundException
        lecteur.close();
    }
}

개선 사항: 이러한 유형의 논리를 처리하려면 일반 제어 구조를 사용하세요.

public class SoldeInsuffisantException extends Exception {
    public SoldeInsuffisantException(String message) {
        super(message);
    }
}

6.3 닫힌 리소스에 try-with-resources 사용하기

try-with-resources 블록은 예외가 발생하더라도 파일이나 연결과 같은 리소스가 자동으로 닫히도록 보장합니다.

나쁜 습관:

public class CompteBancaire {
    private double solde;

    public CompteBancaire(double solde) {
        this.solde = solde;
    }

    public void retirer(double montant) throws SoldeInsuffisantException {
        if (montant > solde) {
            throw new SoldeInsuffisantException("Solde insuffisant pour ce retrait.");
        }
        solde -= montant;
    }

    public static void main(String[] args) {
        CompteBancaire compte = new CompteBancaire(100.0);

        try {
            compte.retirer(150.0);
        } catch (SoldeInsuffisantException e) {
            System.out.println(e.getMessage());
        }
    }
}

개선:

public class AgeInvalideException extends Exception {
    public AgeInvalideException(String message) {
        super(message);
    }
}

6.4 일반적인 예외를 포착하지 마세요

Exception이나 Throwable과 같은 일반적인 예외를 포착하지 마세요. 이렇게 하면 심각한 오류와 예상치 못한 버그가 숨겨질 수 있습니다. 특정 예외를 포착하면 코드를 더 쉽게 읽을 수 있고 유지 관리할 수 있습니다.

나쁜 습관:

public class ValidationUtilisateur {
    public static void validerAge(int age) throws AgeInvalideException {
        if (age < 18 || age > 65) {
            throw new AgeInvalideException("Âge invalide : doit être entre 18 et 65 ans.");
        }
    }

    public static void main(String[] args) {
        try {
            validerAge(17); 
        } catch (AgeInvalideException e) {
            System.out.println(e.getMessage());
        }
    }
}

개선:더 정확한 오류 처리를 위해 특정 예외를 타겟팅합니다.

public class DivisionParZero {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        System.out.println(a / b);  // Lève une ArithmeticException
    }
}

6.5 예외 로깅

예외 로깅을 사용하면 문제를 더 쉽게 추적하고 해결할 수 있습니다. Log4j 또는 SLF4J와 같은 로깅 프레임워크를 사용하여 적절한 로깅 수준(오류, 경고, 정보)을 선택하여 오류를 기록합니다.

나쁜 습관:

public class GestionDesExceptions {
    public static void main(String[] args) {
        try {
            int number = Integer.parseInt("abc"); // Provoquera une NumberFormatException
        } catch (NumberFormatException e) {
            System.out.println("Erreur : la chaîne de caractères n'est pas un nombre valide.");
        }
    }
}

개선:

public class GestionDesExceptions {
    public static void main(String[] args) {
        FileReader fr = null;
        try {
            fr = new FileReader("fichier.txt");
            // Lire le fichier
        } catch (FileNotFoundException e) {
            System.out.println("Erreur : fichier non trouvé.");
        } finally {
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    System.out.println("Erreur lors de la fermeture du fichier.");
                }
            }
        }
    }
}

7. 고급 개념

7.1 비동기 환경의 예외

기본 실행 흐름 외부에서 오류가 발생할 수 있기 때문에 CompletableFuture와 같은 비동기 환경에서는 예외 처리가 더 복잡합니다.

예:

public class GestionDesExceptions {
    public static void main(String[] args) {
        try {
            validerAge(-5); 
        } catch (IllegalArgumentException e) {
            System.out.println("Erreur : " + e.getMessage());
        }
    }

    public static void validerAge(int age) {
        if (age < 0) {
            throw new IllegalArgumentException("L'âge ne peut pas être négatif.");
        }
    }
}

7.2 예외사항 포함

초기 컨텍스트를 유지하면서 예외를 다시 발생시키려면 getCause()를 사용하세요. 이는 애플리케이션의 상위 계층에서 예외를 처리할 때 특히 유용합니다.

예:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class PropagationException {
    public static void main(String[] args) {
        try {
            ouvrirFichier("fichier_inexistant.txt");
        } catch (IOException e) {
            System.out.println("Erreur lors de l'ouverture du fichier : " + e.getMessage());
        }
    }

    public static void ouvrirFichier(String nomFichier) throws IOException {
        FileReader lecteur = new FileReader(nomFichier); // Peut lever FileNotFoundException
        lecteur.close();
    }
}

이 예에서 e는 초기 원인이며 더 쉬운 추적을 위해 getCause()로 검색할 수 있습니다.


8. 단위 테스트 및 예외 처리

단위 테스트는 예외가 올바르게 발생하고 처리되는지 확인합니다. JUnit을 사용하면 메소드가 예상된 예외를 발생시키는지 확인할 수 있습니다.

예:

public class SoldeInsuffisantException extends Exception {
    public SoldeInsuffisantException(String message) {
        super(message);
    }
}

이 예에서 AssertThrows는 0으로 나누는 경우 나누기가 ArithmeticException을 발생시키는지 확인합니다.

예외 처리에 대한 모범 사례를 따르면 Java 코드를 더욱 강력하고 유지 관리하기 쉽게 만들 수 있습니다. 올바른 오류 처리는 애플리케이션의 안정성을 보장할 뿐만 아니라 오류 추적성을 향상시켜 디버깅과 지속적인 개선을 촉진합니다.

결론

요약하자면 Java의 엄격한 예외 처리는 코드 안정성과 유지 관리성을 강화합니다. 명시적인 오류 메시지, 리소스 사용 시도의 현명한 사용, 예외의 가독성 및 테스트 가능성에 대한 주의 등 모범 사례를 채택함으로써 불필요한 중단을 방지하고 보다 안정적인 사용자 경험을 보장합니다. 이를 통해 오류를 효율적으로 감지, 이해 및 수정할 수 있으며 동시에 진화할 수 있는 강력한 코드 기반을 제공할 수 있습니다.

위 내용은 Java의 예외 처리: 전체 가이드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.