[학습목표]
1. 오류 및 예외의 개념에 대해서 이해합니다.
2. 예외 클래스 구조를 이해하고 동작하는 방식을 이해합니다.
3. 예외 발생시 try-catch, finally 문으로 다루는 방법을 배웁니다.
4. 예외를 직접 발생시키는 방법을 배워봅니다.
5. 예외 클래스의 구조가 자바에서 어떻게 구현되어있는지 알아봅니다.
6. 실질적으로 어떻게 예외를 고려하여 프로그래밍을 하는지 알아봅니다.
7. Generic 문법이 왜 필요한지, 어떠한 효용이 있는지 배웁니다.
8. Generic의 세부적인 문법을 배웁니다.
9. 가장 대표적인 Generic의 사용 예시 중 하나인 Collection이 어떻게 구현되어있는지 알아봅니다.
10. Wrapper 객체에 대하여 알아봅니다.
사용자가 숫자가 아닌 문자 입력, 감당할 수 없는 숫자 입력,메모리 부족
=>정의해놔서 대응
오류/예외처리 습관화+>완벽에 가까운 프로그램
<문제 직면 -> 회복 가능한지 여부>
<예외 처리 관점에서 예외 종류>
<주의점>
1. 예외를 어떻게 정의
2. 예외가 발생할 수 있음을 알리고(로직에 flag달아놓음)
3. 어떻게 알고 예외 핸들링하는지
그냥 Exception써도 되지만 상속받아서 구체적인 Exception 적시하는게 좋음
<용어 정리>
checked Excepition
예외 발생하는 상황 인지, 어떤 에러인지 정의
메서드를 선언 할 때 예외가 발생하는 위험한 메서드라는 것을 알렸다!
(throws,throw)
메서드 사용시 예외처리 하지 않으면 컴파일에러!(빨간줄)
예외처리
try : 시도하다
catch : 집다 붙잡다
finally : 마침내
-일단 try해 그리고, 예외 발생하면 잡아(catch)
-그리고, 정상적으로 수행되든, 예외가 발생하든, 마침내 수행되야하는 로직 'finally' 수행해!!
try {
//일단 실행
ourClass.thisMethodIsDanger();//빨간 줄 -> 위험하기 때문에
} catch (OurBadException e) {
//무슨종류 예외 캐치할 것인지 명시 -> 인스턴스 화 System.out.println(e.getMessage());
} finally {
//무조건 여기는 거친다.
System.out.println("우리는 방금 예외를 Handling했습니다. 정상처리되든, 예외사항이 발생하든 여기를 거쳐요!");
}
문제상황을 추상화 일반화 구체화 해서 정의
1. 추상적인 문제
2. 구체적인 오류,예외
3. 더 구체적인 checked exception, Unchecked Exception로 정의
Object클래스 상속
자식으로 Error 클래스 Exception 클래스 -> 그아래 IOError, RuntimeException
* RuntimeException을 상속한 예외들은 UncheckedException,
반대로 상속하지 않은 예외들은 CheckedException으로 구현


컴파일 시점에 알 수 없고, 사용자의 입력에 따라 달라짐->RunTimeException =>UncheckedException
why 연결??
예외 사항 여러개를 한개로 묶어서 처리
CheckedException(컴파일시 핸들링처리해야 에러X=>길어짐)을 UncheckedException으로 포장(Wrapping)함
<원인 예외 다루기 위한 메소드>
initCause():예외 연결
B.initCause(A); => A가 B의 원인
getCause():연결한 예외 반환(어떤 내용인지 조회)
// 연결된 예외
public class main {
public static void main(String[] args) {
try {
// 예외 생성
NumberFormatException ex = new NumberFormatException("가짜 예외이유");
// 원인 예외 설정(지정한 예외를 원인 예외로 등록)
ex.initCause(new NullPointerException("진짜 예외이유"));
// 예외를 직접 던집니다.
throw ex;
} catch (NumberFormatException ex) {
// 예외 로그 출력
ex.printStackTrace();
// 예외 원인 조회 후 출력
ex.getCause().printStackTrace();
}
// checked exception 을 감싸서 unchecked exception 안에 넣습니다.
throw new RuntimeException(new Exception("이것이 진짜 예외 이유 입니다."));
}
}
// 출력
Caused by: java.lang.NullPointerException: 진짜 예외이유
(1)예외 복구
public String getDataFromAnotherServer(String dataPath) {
try {
return anotherServerClient.getData(dataPath).toString();
} catch (GetDataException e) {
return defaultData;
}
}
기본적인 방식이지만, 현실적으로 복구가 가능한 상황이 아닌 경우가 많거나 최소한의 대응만 가능한 경우가 많기 때문에 자주 사용되지는 않습니다.
(2)예외처리회피
public void someMethod() throws Exception { ... }
public void someIrresponsibleMethod() throws Exception {
this.someMethod();
}
<같은 객체 내X>
someMethod()에서 발생한 에러가 someIrresponsibleMethod()의 throws를 통해서 그대로 다시 흘러나가게됨.
(3)예외전환
public void someMethod() throws IOException { ... }
public void someResponsibleMethod() throws MoreSpecificException {
try {
this.someMethod();
} catch (IOException e) {
throw new MoreSpecificException(e.getMessage());
}
}
타입을 유연하게 다루기!
generalized(일반화된)+genetid(유전적인)
효용(타입언어에서 중복되거나 필요없는 코드 줄여줌, 타입안정성 침해하지지 않음)
[기존의 문제]
1)약타입 언어(파이썬, 자바스크립트)->매개변수 타입 지정없이 함수 구현
but, Java는 over-loading해야함(매서드 명 같지만, 매개변수 타입 다르면 다시 구현)
2) 매개변수를 모두 Object로 구현하면
문제 발생)객체 단항 연산자 사용 X(++,--,!,(type), +,-(부호),~(비트반전)), 타입, 순서 구분 안됨 => {}안에 모든 경우의 수 대비해야함!
=>타입 안정성 침해하기 때문에 안됨
=>> Generic으로 구현해 해결
javascript->typescript로 바뀌고 있음
// 1.제네릭은 클래스 또는 메서드에 사용
//클래스 이름 뒤에 <> 문법 안에 들어가야 할 타입 변수를 지정합니다.
//타입변수의 이름을 T로 사용하는 이유는 일종의 컨벤션
public class Generic<T> {
// 2.클래스 내에서 특정한 타입이 들어갈 자리에 대신
private T t;
// 3.메서드의 리턴타입
public T get() {
return this.t;
}
public void set(T t) {
this.t = t;
}
public static void main(String[] args) {
// 4. 제네릭 구현한 클래스를 사용
Generic<String> stringGeneric = new Generic<>();
// 5.매개변수에 String
stringGeneric.set("Hello World");
String tValueTurnOutWithString = stringGeneric.get();
System.out.println(tValueTurnOutWithString);
}
}
<용어 정리>
<제네릭의 제한>
<문법>
1. 다수의 타입변수 사용가능
public class Generic<T, U, E> {
public E multiTypeMethod(T t, U u) { ... }
}
Generic<Long, Integer, String> instance = new Generic();
instance.multiTypeMethod(longVal, intVal);
<? extends T> : T와 그 자손들만 사용 가능<? super T> : T와 그 조상들만 가능<?> : 제한 없음public class ParkingLot<T extends Car> { ... }
ParkingLot<BMW> bmwParkingLot = new ParkingLot();
ParkingLot<Iphone> iphoneParkingLot = new ParkingLog(); // error!
*제한하는 이유 다형성 때문!
4.메서드에 스코프로 제네릭 선언가능
//반환 타입 앞에 <> 사용 -> 해당 메서드에만 적용되는 제네릭 타입변수 선언
//제네릭 클래스내의 static 메소드에서 사용 불가(타입 변수가 인스턴스 변수라서)
//but. 메소드 하나를 기준으로 선언하고 사용은 가능-> 제네릭 메소드
public static <T extends Comparable<? super T>> void sort(List<T> list)
static <T> void sort(List<T> list,Comparator<? super T> c) {...}
public class Generic<T, U, E> {
// Generic<T,U,E> 의 T와 아래의 T는 이름만 같을뿐 다른 변수
static <T> void sort(List<T> list, Comparator<? super T> c) { ... }
}
추상적 자료구조
List(인터페이스)->ArrayList(class), LinkedList(class)로 구현
순서를 가지고 일렬로 나열, 중복허용 <->Set(순서X,중복허용X)
배열(Array)과 리스트 특징
조회관점 :주소만 알면 빠르게 알수 있음(연속적으로 있어서), index로 접근
수정/삭제 관점 : 땡기고 밀고해야해서 느리다.
*검색에는 유리하고 수정 삭제는 불리한 자료구조 -> Stack,Queue로 보완
추상적(인터페이스,추상클래스): 메소드만 정의하고 구현체에서 가져다가 실제로 구현

Integer num = new Integer(17); // Boxing
int n = num.intValue(); // UnBoxingCharacter ch = 'X'; // AutoBoxing(jdk 1.5 이상 부터)
char c = ch; // AutoUnBoxing