프로그램을 완벽하게 만드는 것은 어렵고, 필연적으로 다양한 이상이 발생하게 됩니다. 예를 들어, 프로그램이 인쇄할 때 프린터에 용지가 부족하거나, 메모리가 부족한 등 프로그램 자체에 버그가 있는 경우입니다. 이러한 예외를 해결하려면 예외가 발생한 이유를 알아야 합니다. 일부 일반적인 예외의 경우 특정 대응 계획을 제공할 수도 있습니다. C 언어의 예외 처리는 단순히 함수 반환 값을 통해 구현되지만 반환 값의 의미는 관례에 따라 결정되는 경우가 많습니다. 프로그래머는 모호한 이유를 찾기 전에 많은 양의 정보를 쿼리해야 합니다. C++, Java, Python과 같은 객체 지향 언어에는 더 복잡한 예외 처리 메커니즘이 있는 경우가 많습니다. 여기서는 Java의 예외 처리 메커니즘에 대해 설명합니다.
자바 예외 처리
예외 처리
Java 예외 처리 메커니즘의 상당 부분은 C++에서 비롯됩니다. 이를 통해 프로그래머는 일시적으로 처리할 수 없는 문제를 건너뛰고 후속 개발을 계속하거나 프로그램이 예외를 보다 지능적으로 처리할 수 있습니다.
Java는 비정상적인 조건을 나타내기 위해 일부 특수 개체를 사용하며 이러한 개체를 예외 개체라고 합니다. 예외가 발생하면 Java는 미리 설정된 설정에 따라 현재 상황을 나타내는 객체를 발생시킵니다. 소위 던지기는 특별한 반환 방법입니다. 스레드는 예외 처리기를 만날 때까지 계층별로 메서드 호출을 일시 중지하고 종료합니다. 예외 처리기는 예외 개체를 포착하고 다음과 같이 개체를 기반으로 다음 작업을 결정할 수 있습니다.
사용자에게 예외를 처리하고 프로그램을 계속하여 프로그램을 종료하도록 상기시킵니다.
...
예외 처리기는 다음과 같습니다. try, catch, finally 및 다음 블록으로 구성됩니다. 마지막으로 필요하지 않습니다.
try { ...;}catch() { ...;}catch() { ...;}마지막으로 { ...;}
이 예외 처리기는 try 이후의 프로그램 블록을 모니터링합니다. catch 괄호에는 catch할 예외 유형을 나타내는 매개 변수가 있습니다. catch는 해당 유형과 해당 파생 클래스를 캡처합니다. try 뒤의 프로그램 블록에는 예외 유형에 대해 수행될 작업이 포함됩니다. try에 의해 모니터링되는 프로그램 블록은 두 가지 이상의 예외 유형을 발생시킬 수 있으므로 예외 처리기는 여러 개의 catch 모듈을 가질 수 있습니다. finally 뒤의 프로그램 블록은 예외 발생 여부에 관계없이 실행되어야 하는 프로그램입니다.
잘못될 수 있고 모니터링이 필요한 프로그램은 try에 넣고, 예외를 처리하는 솔루션은 catch에 넣습니다.
다음은 예외 처리를 사용하는 부분 Java 프로그램입니다. 프로그램의 try 부분은 파일에서 텍스트 줄을 읽습니다. 파일을 읽는 동안 IOException이 발생할 수 있습니다.
BufferedReader br = new BufferedReader(new FileReader("file.txt"));try { StringBuilder sb = new StringBuilder(); String line = br.readLine() while (line != null) { sb.append(line) ; sb.append("/n"); line = br.readLine() } 문자열 모두 = sb.toString();} catch(IOException e) { e.printStackTrace(); System.out.println("IO 문제");}마지막으로 { br.close();}
IOException 클래스 객체 e를 포착하면 객체에 대해 작업을 수행할 수 있습니다. 예를 들어, 객체의 printStackTrace()를 호출하여 현재 스택 상태를 인쇄합니다. 또한 중간 범위에 "IO 문제" 프롬프트도 인쇄했습니다.
예외가 있는지 여부에 관계없이 프로그램은 결국 finally 블록에 들어갑니다. finally 블록에서 파일을 닫고 파일 설명자가 차지하는 리소스를 지웁니다.
예외 유형
Java의 예외 클래스는 모두 Trowable 클래스에서 상속됩니다. Throwable 클래스의 객체는 던질(throw) 수 있습니다.
주황색: 선택 취소됨 파란색: 선택됨
던질 수 있는 객체는 두 그룹으로 나눌 수 있습니다. 한 그룹은 확인되지 않은 예외입니다. 예외 처리 메커니즘은 다음을 포함하여 이 예외 그룹에 사용되지 않는 경우가 많습니다.
1. Error 클래스는 일반적으로 Java의 내부 오류 및 리소스 소진과 같은 오류를 나타냅니다. 오류(및 그 파생물)가 발생하면 프로그래밍 수준에서 오류를 해결할 수 없으므로 프로그램을 직접 종료해야 합니다.
2. Exception 클래스에는 특별한 파생 클래스인 RuntimeException이 있습니다. RuntimeException(및 그 파생 항목)은 Java 프로그램 자체, 즉 프로그래머가 프로그래밍하는 동안 실수를 하여 발생합니다. Java 프로그램을 수정하면 RuntimeException을 완전히 피할 수 있습니다. 예를 들어, 상속 관계 없이 한 유형의 객체를 다른 유형으로 변환하는 것은 ClassCastException입니다. 이러한 이상 현상은 방지되어야 하며 방지될 수 있습니다.
나머지는 확인된 예외입니다. 이러한 클래스는 런타임 시 프로그램에 오류를 일으키는 환경과의 프로그래밍 상호 작용으로 인해 발생합니다. 예를 들어, 파일을 읽을 때 파일 자체의 오류로 인해 IOException이 발생합니다. 또 다른 예는 네트워크 서버가 일시적으로 URL 포인팅을 변경하여 MalformedURLException이 발생하는 것입니다. 파일 시스템과 네트워크 서버는 Java 환경 외부에 있으며 프로그래머의 제어 범위 내에 있지 않습니다. 프로그래머가 예외를 예상할 수 있으면 예외 처리 메커니즘을 사용하여 대응 계획을 개발할 수 있습니다. 예를 들어, 파일에 문제가 있으면 시스템 관리자에게 경고가 표시됩니다. 또 다른 예는 네트워크 서버에 문제가 있을 때 사용자에게 이를 알리고 네트워크 서버가 복구될 때까지 기다리는 것입니다. 예외 처리 메커니즘은 주로 이러한 예외를 처리하는 데 사용됩니다.
예외를 던진다
위 프로그램에서는 Java IO API 호출에서 예외가 발생합니다. 충전 및 사용 방법이 있는 다음 배터리 클래스와 같이 자체 프로그램에서 예외를 발생시킬 수도 있습니다.
public class Test{ public static void main(String[] args) { Battery aBattery = new Battery(); aBattery.useBattery(-0.5) }}class Battery { /** * 배터리 증가 * / public void ChargeBattery(double p) { // power <= 1 if (this.power + p < 1.) { this.power = this.power + p; } else { this.power = 1.; } } /** * 배터리 소모 */ public boolean useBattery(double p) { try { test(p) } catch(Exception e); out.println("catch 예외"); System.out.println(e.getMessage()); p = 0.0 } if (this.power >= p) { this.power = this.power - p; return true; } else { this.power = 0.0; return false } } /** * 테스트 사용법 */ private void test(double p) throws Exception // 처리하지 않음 p < 0) { Exception e = new Exception("p는 양수여야 합니다."); throw e } } private double power = 0.0; // 배터리 비율
useBattery()는 배터리 작동을 사용하고 있음을 나타냅니다. useBattery() 메소드에는 전기 사용량을 나타내는 매개변수가 있습니다. 이 매개변수를 테스트하기 위해 test() 메소드를 사용합니다. 이 매개변수가 음수이면 예외가 있다고 생각하고 예외를 발생시킵니다.
테스트에서는 예외가 발생하면(p < 0) Exception 객체 e를 생성하고 문자열을 매개변수로 사용합니다. 문자열에는 예외 관련 정보가 포함되어 있으며 이 매개변수는 필요하지 않습니다. throw를 사용하여 Exception 객체를 던집니다.
useBattery()에는 예외 처리기가 있습니다. test() 메소드는 발생한 Exception을 직접 처리하지 않고 상위 useBattery()에 Exception을 던지기 때문에 test() 정의에서 Exception을 발생시키는 것에 대해 설명할 필요가 있다.
(예외 핸들러가 useBattery()에 없고 상위 수준의 main() 메소드에 있다고 가정하면 useBattery() 정의에 throws Exception도 추가해야 합니다.)
catch에서는 getMessage() 메서드를 사용하여 예외에 포함된 정보를 추출합니다. 위 프로그램을 실행한 결과는 다음과 같습니다.
catch Exceptionp는 양수여야 합니다.
예외 처리기에서는 Exception 클래스 또는 그 파생 클래스의 모든 예외를 포착합니다. 이는 특히 프로그램에서 여러 예외가 발생할 수 있는 경우 문제를 식별하는 데 도움이 되지 않는 경우가 많습니다. 캡처할 보다 구체적인 클래스를 제공할 수 있습니다.
사용자 정의 예외
상속을 통해 새로운 예외 클래스를 만들 수 있습니다. 상속할 때 생성자를 재정의해야 하는 경우가 많습니다. 예외에는 두 개의 생성자가 있습니다. 하나는 매개 변수가 없고 다른 하나는 String 매개 변수가 있습니다. 예를 들어:
클래스 BatteryUsageException은 예외를 확장합니다{ public BatteryUsageException() {} public BatteryUsageException(String msg) { super(msg) }}
파생 클래스에서 더 많은 예외 관련 메서드와 정보를 제공할 수 있습니다.
예외를 사용자 정의할 때 어떤 기본 클래스에서 상속하는지 주의하세요. 보다 구체적인 클래스에는 IOException과 Exception과 같은 더 많은 예외 정보가 포함되어야 합니다.
요약
예외 처리는 문제를 해결하는 동시에 문제를 일으키기도 합니다. 대규모 프로젝트에서는 과도하고 세밀한 예외 처리로 인해 프로그램이 엉망이 되는 경우가 많습니다. 예외 처리는 설계상 단순하지 않으므로 주의해서 사용해야 합니다.