◇ 오류와 예외
- 오류(Error) : 일반적으로 회복이 불가능한 문제
- 예외(Exception) : 일반적으로 회복이 가능한 문제
- 예외의 종류
- 코드 실행 관점에서 예외의 종류
- 컴파일 에러 : .java파일을 .class파일로 컴파일 할 때 발생, 보통 문법오류
- 런타임 에러 : 실행도중 맞닥뜨리는 예외
- 예외 처리 관점에서 예외의 종류
- 확인된 예외(Checked Exception)
- 컴파일 시점에서 확인
- 반드시 예외 처리를 해줘야함
- 미확인된 예외(UnChecked Exception)
- 런타임 시점에서 확인
- 예외 처리가 반드시 필요하지는 않음
- 확인된 예외(Checked Exception)
◇ 예외 발생과 try-catch, finally문
- 예외 처리 흐름
- 예외 정의하기
- 클래스, 메서드를 만들려 예외 위험 알리기(throw, throws)
- 위험한 메서드 사용 시 예외를 handling하기
- try : 일단 위험이 우려되는 코드 실행을 '시도'
- catch : 예외가 발생하면 try문 실행을 중단 시키고 catch문 진행
- finally : 예외발생 여부와 상관없이 실행
- 예외 처리 방법
- 예외 복구
- tru-catch로 예외 처리하고 프로그램을 정상 상태로 복구 - 예외 처리 회피
- 관심사를 분리해서 한 레이어에서 처리하기 위해 사용
- throw를 이용하여 처리 회피 - 예외 전환
- 예외 처리 회피와 비슷하지만, 조금 더 적적한 예외를 던져줌
- 예외 복구
- 연결된 예외(chained exception) : 예외 안에 또 다른 예외를 포함시킴
Throwable initCause(Throwable cause) // 지정한 예외를 원인 예외로 '등록'
Throwable getCause() // 원인 예외를 '반환'
try{
install();
} catch (SpaceException e){
e.printStackTrace(0;
} catch (MemoryException e){
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace(0;
}
위와 같은 코드에서 SpaceException과 MemoryException을 묶어 InstallException으로 예외처리를 하게되면
catch문을 줄일 수 있다(예시는 2가지 뿐이지만 여러가지라고 가정하면 효율적)
다음과 같이 하기 위해선 SpaceException과 MemoryException을 아래와 같이 initCause해야한다.
public void install() throws InstallException{
try{
startInstall();
copyFiles();
} catch (SpaceException e){
InstallException ie = new InstallEception("설치 중 예외 발생");
ie.initCause(e);
throw ie;
} catch (MemoryException e){
// 위와 동일하게 initCause 진행
}
연결된 예외를 사용하면 다음과 같이 결과가 나온다.
InstallException : "설치 중 예외 발생"(대략적인 정보)
Caused by : SpaceException : "설치 할 공간이 부족합니다"(상세 정보)
- checked예외를 unchecked예외로 변경 할 때
throw new RuntimeException(new MemoryException("메모리가 부족합니다."));
→ try-catch문을 안작성해도됨
◇ 제네릭
데이터의 타입을 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것을 의미
아래 코드에서 비슷한 명령의 중복된 코드가 구현되어있다.
class StudentPerson{
public StudentInfo info;
StudentPerson(StudentInfo info){ this.info = info; }
}
class EmployeePerson{
public EmployeeInfo info;
EmployeePerson(EmployeeInfo info){ this.info = info; }
}
아래과 같이 제네릭화 할 수 있다.
class EmployeeInfo{
public int rank;
EmployeeInfo(int rank){ this. rank = rank;
}
}
class Person<T, S>{
public T info;
public S id;
Person(T info, S id){
this.info = info;
this.id = id;
}
}
public class Generic {
public static void main(String[] args) {
Person<EmployeeInfo, Integer> p1
= new Person<EmployeeInfo, Integer>(new EmployeeInfo(1), 1));
}
}
위 코드에서 Generic class에서 new Emolyee(1)이 Person의 T에, 1이 S에 대입되게 된다.
- 제네릭의 생략
class EmployeeInfo{
public int rank;
EmployeeInfo(int rank){ this. rank = rank;
}
}
class Person<T, S>{
public T info;
public S id;
Person(T info, S id){
this.info = info;
this.id = id;
}
}
public class Generic {
public static void main(String[] args) {
EmployeeInfo e = new EmployeeInfo(1);
Integer i = new Integer(10);
Person<EmployeeInfo, Integer> p1
= new Person<EmployeeInfo, Integer>(e, i);
}
}
위 코드에서 아래와 같이 생략이 가능하다.
Person p1 = new Person(e, i);
- 제네릭의 제한
abstract class Info {
public abstract int getLevel();
}
class EmployeeInfo extends Info {
public int rank;
EmployeeInfo(int rank) { this.rank = rank; }
public int getLevel() {
return this.rank;
}
}
class Person<T extends Info> {
public T info;
Person(T info){ this.info = info; }
}
public class Generic {
public static void main(String[] args) {
Person p1 = new Person(new EmployeeInfo(1));
}
}
위 코드에서
class Person<T extends Info> {}
해당 코드의 의미는 T값에 Info의 자식들만이 오도록 '강제' 하는 것이다.
class 대신 interface도 가능하다, interface를 하더라도 제네릭 상속은 implements가 아닌 extends를 사용한다.
'Java & Spring > Java' 카테고리의 다른 글
18일차 - Java강의(쓰레드 명령어) (0) | 2024.08.07 |
---|---|
14일차 - Java강의(쓰레드) (0) | 2024.08.01 |
11일차 - Java강의(계산기 실습, 클래스화, 추상화) (0) | 2024.07.29 |
10일차 - Java강의(제어자, package, import, 상속, this, super) (0) | 2024.07.26 |
9일차 - Java강의(클래스, 필드, 생성자, 멤버, this) (0) | 2024.07.25 |