자바 예외 인터뷰 질문 및 답변

자바는 자바 예외 처리라고 알려진 예외 상황을 처리하기 위한 견고하고 객체지향적인 접근 방식을 제공합니다. 얼마 전에 저는 자바에서의 예외 처리에 대한 긴 글을 작성했으며, 오늘은 면접에서 도움이 될 중요한 자바 예외 처리 질문과 답변을 나열하고 있습니다.

  1. 자바에서 예외란 무엇인가요?
  2. 자바에서의 예외 처리 키워드는 무엇인가요?
  3. 자바 예외 계층 구조를 설명해주세요.
  4. 자바 예외 클래스의 중요한 메서드는 무엇인가요?
  5. 자바 7 ARM 기능과 다중 catch 블록을 설명해주세요.
  6. 자바에서 Checked와 Unchecked 예외의 차이점은 무엇인가요?
  7. 자바에서 throw와 throws 키워드의 차이점은 무엇인가요?
  8. 자바에서 사용자 정의 예외를 어떻게 작성하나요?
  9. 자바에서의 OutOfMemoryError란 무엇인가요?
  10. “Exception in thread main”을 일으키는 다양한 시나리오는 무엇인가요?
  11. 자바에서 final, finally, finalize의 차이점은 무엇인가요?
  12. main 메서드에서 예외가 발생하면 어떻게 됩니까?
  13. 빈 catch 블록을 가질 수 있습니까?
  14. Java 예외 처리 최상의 방법을 제공하십시오?
  15. 아래 프로그램의 문제는 무엇이며 어떻게 해결합니까?

1. Java에서 예외란 무엇입니까?

예외는 프로그램 실행 중에 발생할 수 있는 오류 이벤트로, 일반적인 흐름을 방해합니다. 예외는 사용자에 의한 잘못된 데이터 입력, 하드웨어 장애, 네트워크 연결 실패 등과 같은 다양한 상황에서 발생할 수 있습니다. Java 문장을 실행하는 동안 오류가 발생하면 예외 객체가 생성되고, 그런 다음 JRE는 예외 처리기를 찾아 예외를 처리하려고 합니다. 적절한 예외 처리기가 발견되면 예외 객체가 처리기 코드로 전달되어 예외를 처리하는 것을 예외 처리라고 합니다. 처리기가 없으면 애플리케이션은 예외를 런타임 환경으로 던지고 JRE는 프로그램을 종료합니다. Java 예외 처리 프레임워크는 런타임 오류만 처리하도록 설계되었습니다. 컴파일 시간 오류는 예외 처리 프레임워크로 처리되지 않습니다.

자바에서 예외 처리 키워드는 무엇인가요?

자바 예외 처리에 사용되는 네 가지 키워드가 있습니다.

  1. throw: 때로는 명시적으로 예외 객체를 생성하고 프로그램의 정상 처리를 중지시키기 위해 해당 객체를 throw 하려고 합니다. throw 키워드는 예외를 런타임에 던져 처리하도록 합니다.
  2. throws: 메소드에서 확인된 예외를 throw하고 처리하지 않을 때는 해당 메소드 시그니처에 throws 키워드를 사용하여 호출자 프로그램에 메소드에서 발생할 수 있는 예외를 알려주어야 합니다. 호출자 메소드에서 이러한 예외를 처리하거나 throws 키워드를 사용하여 그것들을 호출자 메소드로 전파할 수 있습니다. throws 절에 여러 예외를 제공할 수 있으며, main() 메소드와 함께 사용할 수도 있습니다.
  3. try-catch: 코드에서 예외 처리를 위해 try-catch 블록을 사용합니다. try는 블록의 시작이며 catch는 예외를 처리하기 위해 try 블록의 끝에 위치합니다. try 블록에는 여러 catch 블록을 사용할 수 있으며 try-catch 블록을 중첩할 수도 있습니다. catch 블록에는 Exception 유형의 매개변수가 필요합니다.
  4. 마침내: finally 블록은 선택적이며 try-catch 블록과만 함께 사용할 수 있습니다. 예외가 실행 프로세스를 중단하기 때문에 닫히지 않는 리소스가 있을 수 있으므로 finally 블록을 사용할 수 있습니다. finally 블록은 예외가 발생하든 말든 항상 실행됩니다.

3. Java 예외 계층 구조를 설명하세요.

자바 예외는 계층적이며 상속은 다양한 유형의 예외를 분류하는 데 사용됩니다. Throwable은 자바 예외 계층의 부모 클래스이며 두 개의 하위 객체인 ErrorException이 있습니다. 예외는 확인된 예외와 런타임 예외로 나뉩니다. 에러는 응용 프로그램의 범위를 벗어난 예외적인 시나리오로, 예를 들어 하드웨어 장애, JVM 충돌 또는 메모리 부족 오류 등을 예측하거나 복구할 수 없습니다. 확인된 예외는 프로그램에서 예상할 수 있는 예외적인 시나리오로, 예를 들어 FileNotFoundException이 있습니다. 이 예외를 catch하고 사용자에게 유용한 메시지를 제공하고 디버깅 목적으로 적절하게 로깅해야 합니다. Exception은 모든 확인된 예외의 부모 클래스입니다. 런타임 예외는 나쁜 프로그래밍으로 인한 것으로, 예를 들어 배열에서 요소를 검색하려고 시도하는 것입니다. 요소를 검색하기 전에 배열의 길이를 먼저 확인해야 합니다. 그렇지 않으면 런타임에서 ArrayIndexOutOfBoundException을 발생시킬 수 있습니다. RuntimeException은 모든 런타임 예외의 부모 클래스입니다.

4. 자바 예외 클래스의 중요한 메서드는 무엇입니까?

예외와 그 하위 클래스는 특정한 메서드를 제공하지 않으며 모든 메서드는 기본 클래스인 Throwable에 정의되어 있습니다.

  1. String getMessage() – 이 메서드는 Throwable의 메시지 문자열을 반환하며 예외를 생성할 때 메시지를 제공할 수 있습니다.
  2. String getLocalizedMessage() – 이 메서드는 하위 클래스가 호출 프로그램에 로캘별 메시지를 제공하기 위해 재정의할 수 있도록 제공됩니다. Throwable 클래스의 이 메서드 구현은 단순히 getMessage() 메서드를 사용하여 예외 메시지를 반환합니다.
  3. synchronized Throwable getCause() – 이 메서드는 예외의 원인을 반환하거나 원인이 알려지지 않은 경우 null을 반환합니다.
  4. String toString() – 이 메서드는 Throwable에 대한 정보를 문자열 형식으로 반환하며 반환된 문자열에는 Throwable 클래스의 이름과 로캘별 메시지가 포함됩니다.
  5. void printStackTrace() – 이 메서드는 스택 추적 정보를 표준 오류 스트림에 출력하며 이 메서드는 오버로드되어 파일이나 스트림에 스택 추적 정보를 작성하기 위해 PrintStream 또는 PrintWriter를 인수로 전달할 수 있습니다.

Java 7의 ARM(자동 리소스 관리) 기능과 다중 예외 처리 블록에 대해 설명하십시오.

하나의 try 블록에서 많은 예외를 처리하려고하면 catch 블록 코드가 매우 더러워 보이고 대부분의 경우 오류를 로깅하기위한 중복 코드로 구성되어 있음을 알 수 있습니다. 이를 염두에두고 Java 7의 기능 중 하나는 다중 예외를 하나의 catch 블록에서 처리할 수있는 다중 캐치 블록이었습니다. 이 기능이 있는 catch 블록은 아래와 같이 보입니다:

catch(IOException | SQLException | Exception ex){
     logger.error(ex);
     throw new MyException(ex.getMessage());
}

대부분의 경우에는 리소스를 닫기 위해 finally 블록을 사용하지만 때로는 리소스를 닫는 것을 잊어 버리고 리소스가 고갈되면 런타임 예외가 발생합니다. 이러한 예외는 디버그하기 어렵고 해당 유형의 리소스를 사용하는 각 위치를 확인하여 닫았는지 확인해야 할 수 있습니다. 따라서 Java 7의 개선 중 하나는 try-with-resources로 리소스를 try 문 내에서 생성하고 try-catch 블록 내에서 사용할 수 있게했습니다. 실행이 try-catch 블록을 벗어나면 런타임 환경이 이러한 리소스를 자동으로 닫습니다. 이 개선 사항이 적용된 try-catch 블록의 샘플은 다음과 같습니다:

try (MyResource mr = new MyResource()) {
            System.out.println("MyResource created in try-with-resources");
        } catch (Exception e) {
            e.printStackTrace();
        }

Java 7 ARM에서 자세히 읽어보십시오.

6. 자바에서 Checked와 Unchecked 예외의 차이점은 무엇입니까?

  1. Checked 예외는 try-catch 블록을 사용하여 코드에서 처리해야하며, 그렇지 않은 경우 메서드는 호출자에게 메서드에서 발생할 수있는 확인된 예외를 알려주기 위해 throws 키워드를 사용해야합니다. Unchecked 예외는 프로그램에서 처리할 필요가 없으며 메서드의 throws 절에 언급할 필요가 없습니다.
  2. Exception은 모든 확인된 예외의 수퍼 클래스이며 RuntimeException은 모든 확인되지 않은 예외의 수퍼 클래스입니다. RuntimeException이 Exception의 하위 클래스임을 유의하십시오.
  3. Checked 예외는 코드에서 처리해야하는 오류 시나리오이며, 그렇지 않으면 컴파일 시간 오류가 발생합니다. 예를 들어, FileReader를 사용하여 파일을 읽을 경우 FileNotFoundException을 throw하고 try-catch 블록에서 catch해야합니다. Unchecked 예외는 대부분의 경우에는 잘못된 프로그래밍으로 인해 발생합니다. 예를 들어, null이 아님을 확인하지 않고 객체 참조에서 메서드를 호출할 때 NullPointerException이 발생합니다. 예를 들어, 문자열에서 모든 모음을 제거하는 메서드를 작성할 수 있습니다. 호출자가 null 문자열을 전달하지 않도록주의해야합니다. 이러한 시나리오를 처리하도록 메서드를 변경할 수 있지만 이상적으로는 호출자가 이를 처리해야합니다.

자바에서 throw와 throws 키워드의 차이점은 무엇입니까?

throws 키워드는 메소드 시그니처와 함께 사용되어 메소드가 발생시킬 수 있는 예외를 선언하는 데 사용되는 반면, throw 키워드는 프로그램의 흐름을 방해하고 예외 객체를 런타임에 전달하여 처리하도록 합니다.

자바에서 사용자 정의 예외를 작성하는 방법은 무엇입니까?

우리는 Exception 클래스나 그 하위 클래스를 확장하여 사용자 정의 예외 클래스를 생성할 수 있습니다. 사용자 정의 예외 클래스는 예외 핸들러에 에러 코드나 기타 예외 관련 정보를 전달하는 데 사용할 수 있는 자체 변수와 메소드를 가질 수 있습니다. 사용자 정의 예외의 간단한 예시는 아래에 나와 있습니다.

package com.journaldev.exceptions;

import java.io.IOException;

public class MyException extends IOException {

	private static final long serialVersionUID = 4664456874499611218L;
	
	private String errorCode="Unknown_Exception";
	
	public MyException(String message, String errorCode){
		super(message);
		this.errorCode=errorCode;
	}
	
	public String getErrorCode(){
		return this.errorCode;
	}
	

}

자바에서 OutOfMemoryError는 무엇인가요?

자바에서의 OutOfMemoryError는 java.lang.VirtualMachineError의 하위 클래스이며, 힙 메모리가 부족하여 JVM에서 발생합니다. 우리는 이 오류를 해결하기 위해 자바 옵션을 통해 더 많은 메모리를 제공함으로써 자바 애플리케이션을 실행할 수 있습니다. $>java MyProgram -Xms1024m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=256m

10. “Exception in thread main”을 발생시키는 다양한 시나리오는 무엇입니까?

일반적인 주 스레드 예외 시나리오 중 일부는 다음과 같습니다:

  • Exception in thread main java.lang.UnsupportedClassVersionError: 이 예외는 자바 클래스가 다른 JDK 버전에서 컴파일되었고 다른 자바 버전에서 실행을 시도할 때 발생합니다.
  • Exception in thread main java.lang.NoClassDefFoundError: 이 예외에는 두 가지 변형이 있습니다. 첫 번째는 클래스의 전체 이름을 .class 확장자와 함께 제공하는 경우입니다. 두 번째 시나리오는 클래스를 찾을 수 없는 경우입니다.
  • Exception in thread main java.lang.NoSuchMethodError: main: 이 예외는 main 메서드가 없는 클래스를 실행하려고 할 때 발생합니다.
  • 주 스레드에서 예외가 발생했습니다. java.lang.ArithmeticException: 메인 메소드에서 예외가 발생할 때, 콘솔에 예외가 출력됩니다. 첫 번째 부분은 메인 메소드에서 예외가 발생했음을 설명하고, 두 번째 부분은 예외 클래스 이름을 출력한 다음 콜론 뒤에 예외 메시지를 출력합니다.

이에 대해 더 자세히 알아보려면 Java Exception in thread main를 참조하세요.

11. Java에서 final, finally, finalize의 차이점은 무엇인가요?

final 및 finally는 java에서 키워드이며, finalize는 메소드입니다. final 키워드는 클래스 변수와 함께 사용될 수 있어서 재할당할 수 없게 만들 수 있으며, 클래스에 확장을 피하기 위해 클래스와 함께 사용될 수 있으며, 서브 클래스에 의해 재정의되는 것을 피하기 위해 메소드와 함께 사용될 수 있습니다. finally 키워드는 try-catch 블록과 함께 사용되어 어떤 예외가 발생하더라도 항상 실행되는 문을 제공하기 위해 사용됩니다. 보통 finally는 리소스를 닫는 데 사용됩니다. finalize() 메소드는 객체가 파괴되기 전에 가비지 수집기에 의해 실행되며, 모든 전역 리소스가 닫혔는지 확인하는 좋은 방법입니다. 이 세 가지 중에서 오직 finally만이 자바 예외 처리와 관련이 있습니다.

12. 주요 메소드에서 예외가 발생하면 어떻게 됩니까?

주요() 메소드에서 예외가 발생하면 Java 런타임이 프로그램을 종료하고 시스템 콘솔에 예외 메시지와 스택 추적을 출력합니다.

13. 빈 catch 블록을 가질 수 있습니까?

빈 catch 블록을 가질 수는 있지만, 이것은 나쁜 프로그래밍의 예입니다. 빈 catch 블록을 가지면 예외가 해당 블록에 의해 잡히더라도 예외에 대한 정보가 없으며, 디버깅하기가 까다로울 수 있습니다. 적어도 콘솔이나 로그 파일에 예외 세부 정보를 기록하는 로깅 문이 있어야 합니다.

14. 몇 가지 Java 예외 처리 최상의 실천 사례를 제공하십시오?

Java 예외 처리와 관련된 몇 가지 최상의 실천 사례는 다음과 같습니다:

  • 디버깅의 용이성을 위해 특정 예외를 사용합니다.
  • 프로그램에서 빠르게 예외를 발생시킵니다 (Fail-Fast).
  • 프로그램의 마지막에 예외를 잡아서 호출자가 예외를 처리하도록합니다.
  • 자원이 닫히도록하려면 Java 7 ARM 기능을 사용하거나 finally 블록을 사용하여 올바르게 닫습니다.
  • 디버깅 목적으로 항상 예외 메시지를 로그에 기록합니다.
  • 더 깨끗한 종료를 위해 다중 catch 블록을 사용합니다.
  • 애플리케이션 API에서 단일 유형의 예외를 throw하는 데 사용자 지정 예외를 사용합니다.
  • 네이밍 규칙을 따르고 항상 Exception으로 끝납니다.
  • javadoc에서 @throws를 사용하여 메서드에서 발생하는 예외를 문서화합니다.
  • 예외는 비용이 들기 때문에 의미가있는 경우에만 throw합니다. 그렇지 않으면 예외를 catch하여 null 또는 빈 응답을 제공 할 수 있습니다.

Java 예외 처리 모범 사례에서 자세히 읽어보십시오.

아래 프로그램의 문제점은 무엇이며 어떻게 수정해야 합니까?

이 섹션에서는 자바 예외와 관련된 몇 가지 프로그래밍 질문을 살펴 보겠습니다.

  1. 아래 프로그램에는 무엇이 문제입니까?

    package com.journaldev.exceptions;
    
    import java.io.FileNotFoundException;
    import java.io.IOException;
    
    public class TestException {
    
    	public static void main(String[] args) {
    		try {
    			testExceptions();
    		} catch (FileNotFoundException | IOException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	
    	
    	public static void testExceptions() throws IOException, FileNotFoundException{
    		
    	}
    }
    

    위의 프로그램은 컴파일되지 않으며 “FileNotFoundException 예외가 대안 IOException에 의해 이미 catch되었습니다”라는 오류 메시지가 표시됩니다. 이는 FileNotFoundException이 IOException의 하위 클래스이기 때문에 발생합니다. 이 문제를 해결하는 두 가지 방법이 있습니다. 첫 번째 방법은 두 예외에 대해 단일 catch 블록을 사용하는 것입니다.

    		try {
    			testExceptions();
    		}catch(FileNotFoundException e){
    			e.printStackTrace();
    		}catch (IOException  e) {
    			e.printStackTrace();
    		}
    

    다른 방법은 multi-catch 블록에서 FileNotFoundException을 제거하는 것입니다.

    		try {
    			testExceptions();
    		}catch (IOException  e) {
    			e.printStackTrace();
    		}
    

    catch 블록 코드에 따라 이러한 접근 방식 중 하나를 선택할 수 있습니다.

  2. 아래 프로그램의 문제점은 무엇입니까?

    package com.journaldev.exceptions;
    
    import java.io.FileNotFoundException;
    import java.io.IOException;
    
    import javax.xml.bind.JAXBException;
    
    public class TestException1 {
    
    	public static void main(String[] args) {
    			try {
    				go();
    			} catch (IOException e) {
    				e.printStackTrace();
    			} catch (FileNotFoundException e) {
    				e.printStackTrace();
    			} catch (JAXBException e) {
    				e.printStackTrace();
    			}
    	}
    
    	public static void go() throws IOException, JAXBException, FileNotFoundException{
    		
    	}
    }
    

    FileNotFoundException이 IOException의 하위 클래스이므로 FileNotFoundException의 catch 블록은 도달할 수 없으며 “FileNotFoundException에 대한 도달할 수 없는 catch 블록입니다. 이미 IOException에 대한 catch 블록으로 처리되었습니다”라는 오류 메시지가 표시됩니다. 이 문제를 해결하려면 catch 블록의 순서를 수정해야 합니다.

    			try {
    				go();
    			} catch (FileNotFoundException e) {
    				e.printStackTrace();
    			} catch (IOException e) {
    				e.printStackTrace();
    			} catch (JAXBException e) {
    				e.printStackTrace();
    			}
    

    JAXBException은 IOException이나 FileNotFoundException과 관련이 없으며 위의 catch 블록 계층 구조 어디에나 배치할 수 있음을 유의하십시오.

  3. 아래 프로그램의 문제점은 무엇입니까?

    package com.journaldev.exceptions;
    
    import java.io.IOException;
    
    import javax.xml.bind.JAXBException;
    
    public class TestException2 {
    
    	public static void main(String[] args) {
    		try {
    			foo();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}catch(JAXBException e){
    			e.printStackTrace();
    		}catch(NullPointerException e){
    			e.printStackTrace();
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    	}
    
    	public static void foo() throws IOException{
    		
    	}
    }
    

    프로그램이 컴파일되지 않는 이유는 JAXBException이 확인된 예외이고 foo() 메서드가 호출 메서드에서 이 예외를 던져야하기 때문입니다. “JAXBException에 대한 도달할 수 없는 catch 블록입니다. 이 예외는 try 문에서 발생하지 않습니다”라는 오류 메시지가 표시됩니다. 이 문제를 해결하려면 JAXBException의 catch 블록을 제거해야합니다. NullPointerException을 catch하는 것은 유효합니다. 이는 확인되지 않은 예외입니다.

  4. 아래 프로그램의 문제점은 무엇입니까?

    package com.journaldev.exceptions;
    
    public class TestException3 {
    
    	public static void main(String[] args) {
    		try{
    		bar();
    		}catch(NullPointerException e){
    			e.printStackTrace();
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    		
    		foo();
    	}
    
    	public static void bar(){
    		
    	}
    	
    	public static void foo() throws NullPointerException{
    		
    	}
    }
    

    이것은 함정입니다. 코드에 문제가 없으며 정상적으로 컴파일됩니다. 예외 또는 확인되지 않은 예외를 항상 메서드의 throws 절에 없더라도 잡을 수 있습니다. 마찬가지로 throws 절에서 확인되지 않은 예외를 선언하는 메서드(foo)를 사용하면 프로그램에서 그것을 처리할 필요는 없습니다.

  5. 아래 프로그램의 문제점은 무엇입니까?

    package com.journaldev.exceptions;
    
    import java.io.IOException;
    
    public class TestException4 {
    
    	public void start() throws IOException{		
    	}
    	
    	public void foo() throws NullPointerException{
    		
    	}
    }
    
    class TestException5 extends TestException4{
    	
    	public void start() throws Exception{
    	}
    	
    	public void foo() throws RuntimeException{
    		
    	}
    }
    

    위의 프로그램은 컴파일되지 않습니다. 왜냐하면 하위 클래스에서 start() 메서드의 시그니처가 상위 클래스와 일치하지 않기 때문입니다. 이 문제를 해결하기 위해 우리는 하위 클래스의 메서드 시그니처를 정확히 상위 클래스와 같게 변경하거나, 아래에 표시된 것처럼 하위 클래스 메서드에서 throws 절을 제거할 수 있습니다.

    @Override
    	public void start(){
    	}
    
  6. 아래 프로그램의 문제점은 무엇입니까?

    package com.journaldev.exceptions;
    
    import java.io.IOException;
    
    import javax.xml.bind.JAXBException;
    
    public class TestException6 {
    
    	public static void main(String[] args) {
    		try {
    			foo();
    		} catch (IOException | JAXBException e) {
    			e = new Exception("");
    			e.printStackTrace();
    		}catch(Exception e){
    			e = new Exception("");
    			e.printStackTrace();
    		}
    	}
    
    	public static void foo() throws IOException, JAXBException{
    		
    	}
    }
    

    위의 프로그램은 컴파일되지 않습니다. 다중 캐치 블록의 예외 객체가 final이기 때문에 값을 변경할 수 없습니다. “다중 캐치 블록의 매개변수 e에 할당할 수 없습니다”라는 컴파일 시간 오류가 발생합니다. 이 오류를 해결하려면 “e”를 새 예외 객체에 할당하는 것을 제거해야 합니다. 자세한 내용은 Java 7 다중 캐치 블록을 참조하십시오.

자바 예외 인터뷰 질문에 관한 내용은 여기까지입니다. 이것이 마음에 드시길 바랍니다. 앞으로 목록에 더 많은 내용을 추가할 예정이니, 향후 사용을 위해 즐겨찾기에 추가해 주세요.

Source:
https://www.digitalocean.com/community/tutorials/java-exception-interview-questions-and-answers