일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- springboot
- 페이로드
- 배열빈도수
- 포트포워딩
- 백준1946
- docker
- 모래시계출력
- SpringApplication
- name=springapplication
- 리눅스계열
- Decapsulation
- 도커권한설정
- 리눅스환경
- javax.management.instancenotfoundexception: org.springframework.boot:type=admin
- 네트워크모델
- jmx
- 우분투
- instancenotfoundexception
- 디비버
- 배열복사
- ubuntu
- 유니캐스트
- 포트포워딩 안될때
- 도커
- dbeaver
- 백준
- 오름차순
- 배열최소값최대값
- wan
- 브로드캐스트
- Today
- Total
다잘하고싶어
자바 예외처리 본문
목차
☑️에러와 예외
- 어떤 원인에 의해 오동작하거나 비정상적으로 종료되는 경우
- 코드를 통해서 프로그램의 비정상적 종료를 막을 수 있는가
- 심각도에 따른 분류
- Error
- 메모리 부족, stack overflow 와 같이 일단 발생하면 복구할 수 X
- 프로그램의 비정상적 종료를 막을 수 없음, 디버깅 필요
- Exception
- 읽으려는 파일이 없거나, 네트워크 연결이 안되는 등 수습할 수 있는 비교적 상태가 약한 것들
- Error
- 예외는 처리하지만, 에러는 처리하지 않는다.
⛔ 예외(Exception) 처리
- 예외 처리 → 👉불확실성👈 을 어떻게 다룰 것인가?
☑️ 예외처리란?
- 예외 발생 시 프로그램의 비정상 종료를 막고 정상적인 실행상태를 유지하는 것
- 예외의 감지 및 예외 발생 시 동작할 코드 작성 필요
✅ 예외처리를 하는 이유
- 주된 관심사와 보조 관심사 분리( 메서드의 본 기능에 집중 )
- 예외 → 메서드를 사용하는 사람이 처리하도록 넘김..?
- 발생할 수 있는 문제를 미리 알려주는 효과.
- 메서드를 잘못사용하는 것을 방지
☑️ 예외클래스의 계층
- Error 는 처리하지 않는다!
Checked exception
- 예외에 대한 대처코드가 없으면 컴파일이 진행되지 않음
- 코드 작성 시 예외에 대한 작성 필수 ( try catch문, throws )
- Exception 클래스를 상속받는 것들( RuntimeException 은 상속받지 않아야 함)
Unchecked exception
- RuntimeException 을 상속받는 것들
- 예외에 대한 대처코드가 없더라도 컴파일 진행됨.
예외 예시
⇒ 인덱스 범위를 벗어남.
⇒ 0으로 나눌 수 없음.
⇒ 숫자로 바꿀 수 없음.
✅ 예외는 언제 발생할까?
⇒ new 예외생성자() → 예외 객체 throw new
⇒ 즉, 예외 객체를 던질 때 발생
내부적으로 객체를 만들어서 직접 예외를 발생시킬 수 있음
☑️ 예외 처리 키워드
✔️ 직접 처리
- try
- catch
- finally
✔️간접 처리
- throws
- 보통은 예외 객체가 발생하는 메서드를 호출하는 쪽이 처리함
✔️ 사용자 정의 예외 발생 시킬 때
- throw
✅ try ~ catch 구문
try {
//예외가 발생할 수 있는 코드
}catch{
//예외가 발생했을 때 처리할 코드
}
Q. Exception 은 빨간 줄 뜨고, NumberFormatException 은 빨간 줄 안뜨는 이유?
⇒ Exception 은 CheckedException이고 , NumberFormatException 은 UnCheckedException 이기 때문이다
예외 처리 예시 코드
public class Test1 {
public static void main(String[] args) {
int [] nums = {10};
try {
System.out.println(nums[1]);
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("배열의 크기 초과 시 대처 코드");
}
System.out.println("프로그램 정상 종료");
}
}
✅ Exception 객체의 정보 활용
- Throwable의 주요 메서드
- public String get Message() : 발생된 예외에 대한 구체적인 메세지 반환
- public Throwable getCause() : 예외의 원인이 되는 Throwable 객체 또는 null 반환
- public void printStackTrace : 예외가 발생된 메서드가 호출되기까지의 메서드 호출 스택을 출력함, 디버깅의 수단으로 주요 사용.
✅ try ~ catch 문에서의 흐름
1️⃣ try 블록에서 예외가 발생 → 2️⃣ JVM 이 해당 Exception 클래스의 객체 생성 후 던짐(throw) → 3️⃣던져진 exception 을 처리할 수 있는 catch 블록에서 받은 후 처리 ( 적당한 catch 블록을 만나지 못하면 예외처리 실패) → 4️⃣ 정상적으로 처리되면 try-catch 블록을 벗어나 다음 문장 진행
☑️ 다중 exception handling
- try 블록에서 여러 종류의 예외가 발생할 경우
- 하나의 try 블록에 여러개의 catch 블록 추가 가능(예외 종류별로 catch 블록 구성)
✅ 다중 catch 문장 작성순서 유의사항
- JVM 이 던진 예외는 catch 문장을 찾을 때 다형성이 적용됨
- 상위 타입의 예외가 먼저 선언되는 경우 뒤에 등장하는 catch 블록은 동작할 기회가 없음
- 상속 관계가 없는 경우는 무관
- 상속 관계에서는 작은범위(자식)에서 큰 범위(조상)순으로 정의
실습코드
Q. 아래의 9번, 11번 라인에 에러가 뜨는 이유?
⇒ 이미 7번라인에서 가장 큰 예외로 처리했으므로, 그 밑에 라인에는 도달할 수 없다는 에러가 발생한다.
⇒ 즉, 다중 예외처리를 할 때는 순서가 중요하다,
⇒ 해당하는 예외를 만나지 못하면 예외는 처리되지 않는다.
✅ | 연산자를 이용해서 한번에 다양한 종류의 예외처리하기
public class Test3 {
public static void main(String[] args) {
try {
int num = Integer.parseInt("hellohello");
}catch(ArithmeticException | ArrayIndexOutOfBoundsException | NumberFormatException e) {
System.out.println("여러개의 예외 한번에 처리하기");
}
}
}
✅ try- catch- finally 구문을 이용한 예외 처리
- finally 는 예외 발생 여부와 상관없이 언제나 실행
- 중간에 return 을 만나는 경우도 finally 블록을 먼저 실행 후 return 실행
Q1. 아래의 코드에서 출력되는 코드의 숫자들은?
Q2. 아래의 코드에서 출력되는 코드의 숫자들은?
⇒ 8번라인에서 에러가 터져서 11번라인에 걸려서 12번 라인이 실행된다. 즉, 9번과 10번라인은 아예 실행되지 않으므로, return을 만나서 메인메소드가 종료되지 않고 나머지 코드들이 실행되는 것.
Q3. 아래의 코드에서 출력되는 코드의 숫자들은?
⇒ 8번라인에서 11번,12번 라인이 실행되고 return문을 만나서 실행하기전에 finally 를 실행한 후 다시 return 으로 돌아가서 main 메소드가 종료된다. 따라서 그 이후 17,18번 라인이 실행되지 않음.
⇒ finally 는 언제나 실행된다.
⇒ try ~ catch ~finally 가 종료된 후의 코드는 언제나 실행되는 것은 아니다.
✅ finally 가 필요한 이유 + 상황
⇒ DB를 연결할 때
- 연결을 종료할 때, 관련된 리소스들을 정리할 때 필요하다.
⇒ 파일 입출력 시
- 입출력 스트림, 관련된 리소스들을 정리할 때 필요하다.
✅ throws 키워드를 통한 처리 위임
- method 에서 처리해야할 하나 이상의 예외를 호출한 곳으로 전달 ( 처리 위임 = 책임 전가 )
- 예외가 없어지는 것이 아니라 단순히 전달됨
- 예외를 전달받은 메서드는 다시 예외 처리의 책임 발생
✅ checked exception 과 throws
- checked exception 은 반드시 try ~ catch 또는 throws 필요
- 필요한 곳에서 try ~ catch 처리
- main 메소드에서도 throws 로 처리할 수 있다 ⇒ 단, 예외 처리 되지 않음. 예외 발생 시 프로그램 종료
✅ runtime exception 과 throws
- runtime exception은 unchecked exception
- runtime exception 은 throws 하지 않아도 전달 되지만, 결국 try~ catch 로 처리해야 함.
Q. method1 과 method2 모두 문제가 발생할만한 요소를 가지고 있으나
16번 라인에만 에러표시. 왜?
⇒ FileNotFoundException 은 Checked Exception 이고, 예외를 처리하지 않으면 컴파일되지 않음.
method2 에 throws 키워드를 사용하여 예외를 넘기면?
9번 라인에 빨간줄.
⇒ throws 키워드를 이용해서 내 메서드 안에서 일어날 수 있는 예외를 나를 호출한 곳으로 전가시킴
⇒ NumberFormatException 은 UnChecked Exception 이므로, 처리하지않아도 컴파일 됨.
⇒ 예외처리가 강제사항이 아님
✅ 로그 분석과 예외의 추적
- Throwable의 printStackTrace 는 메서드 호출 스택 정보 조회 가능
- 최초 호출 메서드에서부터 예외 발생 메서드 까지의 스택 정보 출력
- 꼭 확인해야할 정보?
- 어떤 예외인가 ⇒ 에외종류
- 예외 객체의 메세지는 무엇인가 ⇒ 예외 원인
- 어디서 발생했는가 ⇒ 디버깅 출발점
✅ 메서드 재정의와 throws
- 메서드 재정의 시 조상클래스 메서드가 던지는 예외보다 더 큰 부모예외를 던질 수 없다.
☑️ CheckedExceptionTest
선택지(1) throws 로 던지기
선택지(2) try ~ catch 로 내가 처리하기
Q. 아래 빨간줄 이유?
스테틱 영역에서 non-static 영역에 있는 것들에 접근해서.
해결하려면? 인스턴스로 생성해주기.
그럼에도 빨간줄 이유는?
예외처리를 해주지 않아서
해결완료
☑️ UnCheckedExceptionTest
빨간줄 안뜨지만 실행하면 예외난다.
⇒ 상속받은 클래스는 부모보다 더 큰 예외를 던질 수 없다.
⇒ 자식은 부모보다 더 큰 예외를 발생시킬 수 없다.
인스턴스 객체를 하나 만든 것. → 예외처리를 해줘야한다.
☑️ 사용자 정의 예외
- API 에 정의된 exception 이외에 필요에 따라 사용자 정의 예외 클래스 작성
public class NoSpaceException extends Exception{
public NoSpaceException() {
super("더이상 공간이 없어요");
}
}
public class FruitsNotFoundException extends Exception{
public FruitsNotFoundException(String name) {
super(name +"에 해당하는 과일은 없어요ㅜ");
}
}
FruitsNotFoundException 만들기
public static void getFruit2(String name) throws FruitsNotFoundException {
for (int i = 0; i < fruits.length; i++) {
if(fruits[i] != null && fruits[i].equals(name)) {
fruits[i] = null;
return;
}
}
throw new FruitsNotFoundException(name);
}
예외 객체를 생성할 때 throw
메소드에서 다른 메소드로 예외를 떠넘길때 throws
NoSpaceException 만들기
//배열에 null 인 지점에 과일을 저장하도록 작성
//단 공간이 없다면 NoSpaceException 이라는 사용자 정의 예외를 작성하고 해볼 것
public static void setFruit(String name) throws NoSpaceException {
for (int i = 0; i < fruits.length; i++) {
if(fruits[i] == null) {
fruits[i] = name;
return;
}
}
throw new NoSpaceException();
}