22.04.29 - Generic, 향상된 for문(enhanced for), 예외(Exception)
Generic - 제네릭
- 컬렉션 때문에 나온 애
- 타입 제한을 위해 사용 - ( 주로 컬렉션 )
- 설명서에 많이 나오기 때문에 알아야 한다.
- 컬렉션은 타입 상관없이 다양하게 넣을 수 있는 것이 장점이자 단점이다.
제네릭 예시 )
- 집에 서랍이 하나 있는데 – 세면용품, 공책, 이것저것 다 있다.
- 꺼낼 때마다 매번 세면용품인지 공책인지 확인해야 한다. - 번거롭고 힘들다
- 그래서 이 서랍에 이런 것만 넣어주세요 하는 것이 제네릭!
제네릭 예시 )
- 서랍에 세면용품만 넣게 해 주면 꺼낼 때 세면용품인지 확인할 필요 없다!
- 컬렉션에다가 들어갈 수 있는 타입 제한할 수 있다.
제네릭 예시)
- 서랍에서 매번 꺼낼 때마다 세면용품인지 확인할 필요 없이 다 세면용품이다.
실습으로 제네릭 알아보기!
1. 제네릭 사용 안 한 상태 - ArrayList에 자료를 추가해보기
- 메서드 하나 만들어서 실습 진행
- List타입 ArrayList() 사용해서 실습해보자
1-1 어레이 리스트 al에 - 값 입력하기
1-2 입력한 값을 가져와서 모두 더해주기
1-3 출력 테스트
- 오브젝트를 int로 넣어주려니까 오류 난다. ( 사용할 때마다 형 변환 필요 )
- 60 정상 출력 확인
2. 제네릭<> 사용해보기
- <>없이 List 사용 시 - 안에 데이터 사용할 때마다 매번 형 변환해줘야 한다.
- 이런 상황에 사용하기가 불편하다 - 제네릭 사용해보자
2-1 제네릭 적용해주기
제네릭 사용 예시 : List<String> = new ArrayList<String>();
제네릭 사용 예시 : List<String> = new ArrayList<>(); <- 선호함
- < > 안에 기본자료형은 안된다. Object형이라서
2-2 출력 테스트
- int형만 들어오도록 제한을 걸어주었다. - 들어있는 것은 다 int형 애들이다.
- 꺼내서 사용할 때마다 - int형으로 형 변환하는 과정 필요 없어짐.
제네릭을 사용했을 때의 특징
1 - 입력되는 타입의 제한 가능
- String 타입 입력 안된다 에러 - 인티저 타입 넣어라 에러 난다.
- 제네릭으로 < Integer > 지정 안 해줬으면 모든 Object 타입 가능하다.
- int형만 들어오도록 제한을 걸어주었다. - 들어있는 것은 다 int형 애들이다.
2 - 입력 데이터 사용할 때마다 형 변환하는 과정 생략 가능
- 매번 꺼낼 때마다 형 변환 필요 없다.
- ex) 서랍에서 매번 꺼낼 때마다 세면용품인지 확인할 필요 없이 다 세면용품이다.
향상된 for문 사용해보기 – enhanced for
- 컬렉션에서는 안에 있는 모든 것을 꺼내서 쭉 작업하는 경우가 많다.
- 그럴 때마다 코드 다 써주는 것이 비효율적이다. 그래서 나온 것이 향상된 for문
1. 값을 빼와서 더해주는 부분 - 일반 for문으로 부분 바꿔보기
- 길이를 알기 위해 size() 함수 사용
- List에서는 size( )
- 배열처럼 .length 사용 안된다.
2. 값을 빼와서 더해주는 부분 - 향상된 for문으로 부분 바꿔보기
1. 초기화/조건식/증감식 부분 수정
- for( int x : al )
- al 리스트에서 하나씩 꺼내서 그때마다 x에 저장한다는 의미
- x를 int 형으로 지정해 줄 수 있는 이유 = al에 제네릭이 지정되어있기 때문이다! check
- 밑에 수행문 수정하면 끝!
2. 수행문 수정
향상된 for문 끝!
+@ 컬렉션 이야기
모든 타입 받는 것이 컬렉션 장점인데 왜 제네릭으로 제한해서 사용하나?
- 컬렉션을 사용하면서 데이터들을 이용할 때 문제 되는 상황들 + 형 변환 필요 생김
- 그래서 컬렉션 사용할 때 거의 99% 사용한다.
사용하는 이유 1 : 자료구조의 특징을 활용하기 위해서 사용한다.
- 제네릭해주면 배열과 다를 게 없는데 왜 컬렉션사용? - 자료구조 특징 활용
- ex) 배열은 태어날 때부터 size-fix / List 는 size-flexible 가변
- ex) 배열은 한 칸 한 칸이 인덱스가 있고, 데이터가 들어가 있는 구조
- ex) List는 하나하나의 노드들은 - 실제 데이터가 들어있는 곳과 다음 노드 가리키는 공간으로 구성
사용하는 이유 2 : 사용하는 타입을 모를 경우에도 사용
- 실제 runTime시에만 타입을 알 수 있는 상황이 있다. 그런 상황에도 사용
+@ List 와 Array의 차이점
1. 배열 array는 인덱스로 내가 찾으려고 하는 값에 한 번에 접근 가능array[ 2 ] 하면 - 3 접근
2. ArrayList는 3번째(인덱스2) 노드를 찾아가려면 맨 앞에 있는 애부터 순서대로 찾아가야 한다.
- why? 인접해서 있는 애들이 아니라 중구난방으로 존재하는 애들이다.
- 다음 애가 누군지 가리키는 데이터 필요 : 100번째 찾아가려면 100번 필요
- 검색하는 상황에서의 자료 구조로 ArrayList는 적합하지 않다.
예외처리
> 예외란?
- 너무 크리티컬 하지 않은 에러
>에러의 종류
- 컴파일 에러
- 번역 단계에서 에러 발생하는 것. 행복한 것! 눈에 보이고 / 수정 쉽고 /
- int a = “abc”; 컴파일 에러 발생
- 런타임 에러
- 실행 단계에서 에러 발생하는 것. 심각스. 눈에 안보이고 / 찾기도 어렵다.
- ex) int a = 1/0; -> 컴파일 에러 안남. 런타임 에러 발생
예외 발생 상황 테스트해보자!
컴퓨터 입장에서 실행 체크
- 프로그램 실행됐다 – 메인 메서드 찾아가서 실행한다.
- 11번 라인 출력해준다.
- 13번 라인 – 등호가 있으니까 오른쪽 먼저 계산 – 1/0 못하는데. 끝내버린다. 멈춰있는다. 죽어버린다.
- 프로그램 종료
- 예외상황 발생 시를 대비 - 예외 처리가 필요하다.
- 실행 중에 예외상황 발생 시 끝내거나 멈추지 않고, 왜 멈췄는지 exception으로 알려준다.
- 이 exception을 처리해주자
> 예외처리의 2가지 방법 - try/catch 와 throws
예외 처리 방법 1 - try / catch
- 예외 발생된 순간에 - 잡아서 바로 처리해주는 방식이다
- 예외가 발생한 부분에서 바로 잡아와서 종료까지 흘러가도록 해주자
- try / catch
컴퓨터 입장에서
- 19라인 - try 만나서 {} 실행한다. 20라인 -등호가 있으니 오른쪽 실행 예외 발생 -
- exception 나왔다고 튀어나가려고 하니까
- 21라인 - catch에 있는 애가 잡아다가 데리고 온다.
- 22라인 – 실행된다.
정확한 exception 처리해주려면 예외 타입에 맞는 거 써주어야 한다..
- 부모 타입의 Exception으로 받아준 것이라서 ..잡아줄 수 있었음(다형성)
- 모든 exception 들은 부모로 Exception 가지고 있다.
- 예외 상황 보기 위해서 출력(e) 해도 되는데
- 빨간색으로 출력되는 것 printStackTrace();
+@ 여러 가지 예외 상황 잡아줄 시에 try/catch 할 경우에 주의사항
>더 큰 범위의 Exception 처리를 먼저 해주면 무조건 걸림.
>밑에 있는 애까지 갈 일이 없다 - 에러 난다..
예외 처리 방법 2 - throws
- 방법 1 - try/catch -> 발생된 순간에 - 잡아서 바로 처리해주는 방식이다
- 방법 2 - throws -> 예외 던지기, 남에게 던지기
나를 호출했던 곳 ( main 메소드의 t.test(); 호출해줬던 곳으로 예외처리 넘어간다.
예외 던지기 상황 Method 호출 상황을 통해 이해하기
- 우리가 했던 메서드 작성 방법에 사실은 예외가 숨어져 있었다..
메서드가 실행되는 시점은?
- 메소드가 호출될 때
- 예외를 던진다 하면은 – 나를 호출한 애한테 예외처리를 던진다는 것
- 메소드 호출할 때 파라미터를 가지고 - 메서드 안으로 오듯이
- 메소드 안에서 예외가 발생하면 - 예외를 가지고 호출한 곳으로 던져버린다.
+@ 메서드 헤드(선언부)에 throws 있으면 사용하는 곳에서는 에러가 넘어오지 않더라도 넘어 올 상황에 대비해서
+@ 메서드를 사용하는 모든 곳에서 try/catch 나 throws 다 필요하다 ( throws 여러 번 해도 ok) but
+@ main 메서드에서는 throws 하면 안 된다.
+@ 메인 메서드를 호출한 곳은 프로그램. 프로그램에게 던지는 것으로 안된다.
내가 만든 예외상황!
양수 입력받으면 안 되는 프로그램에서
양수가 입력되었을 때 내가 만든 예외 상황이 발생하도록 해주기
1. 클래스 만들고 extends Exception
2. 원래 하던 if문으로 하는 방식 체크
3. 양수 입력 시 내가 만든 예외처리 발생하도록 해주기.
왜 직접 예외를 만들었냐?
- 이런 상황(양수 입력)이 java에서 만들어놓은 예외상황은 아니지만
- 내가 이런 상황에서는 예외가 발생하도록 하고 싶다.
- thorw new MyException();
- 양수를 입력하면 예외상황 발생하도록 해준다.
왜 이렇게 사용하냐?
1. if문은 한계가 있다.(return 값을 아무리 잘 활용한다 해도))
예외처리는 try/catch 나 throws를 활용할 수 있다.
2. main메서드로 예외상황을 던질 때 너무 넓은 범위인 Exception을 던지면 처리하기 힘들 수 도 있다.
내가 무슨 예외상황인지 잡아서 던져주면 main에서 예외 처리하기 수월해진다.
3. 방금 잡은 예외상황이 MyException이구나 종류를 알려줄 수 있다!
Question Time
Q. 예외처리를 미루는 이유?
- 한 메서드 안에서 어디서 에러가 발생할지 모르니까. ( 각각 try/catch 감싸주기 어렵다 )
- 작은 범위에서 혼자서 try/catch 해버려서 처리해버리면 더 큰 범위에서 봤을 때
- 얘가 에러 처리를 해서 이런 결과가 나온 건지 수행이 잘 되어서 이런 결과가 나왔는지 확인 불가능
- – 결과물이 다를 수 있다.
- 예시 상황 들어서 설명
- 사장이 주방 직원에게 치킨 튀겨라 명령
- 주방 직원이 에러 발생(( 혼자 처리하려고 try/catch로 치킨 말고 밀가루만 튀김 ) 완성품 -> 사장 전달
- 사장은 완성품 받아서 배달 직원에게 전달
- 받은 손님은.... 극대노
5. 예외상황이 발생하면 직접 처리하지 말고 사장인 나에게 알려줘라.
- 밑에 4군데 어디서 문제가 발생하더라도 사장이 처리하도록..
- 치킨이 없어서 문제였던 / 밀가루가 없어서 문제였던 / 기름이 없었던 /
- 책임은 사장에게 있다는 것!
Q. 예외 발생을 대비하는 이유는?
- up/down 게임에서 1~100 사이의 숫자 입력하라고 했는데
- 문자열을 입력한다던지
- 범위 벗어난 수 입력한다던지
review
컬렉션과 제네릭 + 향상된 for문
배웠던 3가지의 주제의 목표는
개발자의 작업을 더 효율적이고 편리하게 해 주어서
개발에 집중할 수 있는 환경을 만들어주기 위한 것 같다.
이미 만들어놓은 자료구조들의 특징과 기능들을 사용하게 해 준 컬렉션
컬렉션 사용 시 데이터관리와 형변환의 번거로움 해결해준 제네릭
제네릭 사용시 자주 사용하는 for문을 향상해준 enhanced for
점점 더 개발자를 위해 많은 것이 갖춰 질 것 같다.
이처럼 이제 개발자는 세세한 코딩도 중요하겠지만
주어진 상황에 맞춰서 어떤 자료 구조와, 특징, 기능들을 사용할지
큰 그림을 그릴 수 있는 능력도 갖춰야 할 것 같다.
예외처리
Exception 처리를 미룬다 / 던지다라고 throws를 쉽게 생각했었는데
thorws Exception 하면 이 Exception이
어떻게 처리가 되는지, 어떻게 돌아다니는지를 알 수 있어서 좋았다.
+ 예외처리를 지금 수준에서 할지 던져서 상위 수준에서 할지도
생각해보아야겠다고 느꼈다.
+ 왜 예외상황 발생을 대비해서 try/catch 해주는지도
해킹 천재 고등학생과 원시인의 예시로 확 와닿았다.ㅎㅎ