Generic 을 왜 사용하기 시작했을까요?
이 질문에 대해서 알아보기 위해서 글을 작성했습니다
Generic 이 없었을 때는 어땠을까요?
Generic 이 없이 작성된 과거의 코드를 가져와보도록 하겠습니다
실제로 작성할 수 있는데요
문제가 되는 상황이 2가지나 보이는데요
1. String을 직접 꺼내도 String이 나오지 않고, Object 형태로 나와서 캐스팅을 하지 않는다면 컴파일 에러가 발생하게 됩니다
2. String 만 들어있을 것으로 기대되는 ArrayList 에 int 값을 넣으려고 시도해도 에러가 발생하지 않습니다
실제로 그 위치까지 가서 String으로 변환을 시도했을 때 런타임에 ClassCastException 이 발생합니다
이를 generic으로 해결할 수 있습니다
실제로 int타입을 넣으려고 시도를 하는 순간에 바로 에러가 발생합니다
Generic을 사용했을 때 장점
1. 런타임에서 발생하는 ClassCastException 이 컴파일 타임으로 옮겨진다
런타임에 발생하는 에러의 경우 디버깅이 매우매우 까다롭습니다. 실제로 그 경우가 발생하기 전까지는 에러가 있는지를 알 수 없다는 점이 문제인데요
2. String 으로 타입 캐스팅을 하지 않아도 바로 변환이 됩니다
직접 instanceOf 같은 연산자를 통해서 확인하지 않아도 된다는 점이 정말 커다란 장점이 됩니다
타입 파라미터 이름짓는 규칙도 있습니다(from oracle)
- E — Element (used extensively by the Java Collections Framework)
- K — Key
- N — Number
- T — Type
- V — Value
- S,U,V etc. — 2nd, 3rd, 4th types
Generic은 다른 말로 실체화불가 타입이라고도 합니다.
컴파일 시에는 남아있지만, 실제 런타임에는 지워지기 때문이기도 한데요
위의 코드를 컴파일한 결과가 아래 코드입니다
실제로 실행할 때는 <>연산자가 없어지고, 마지막에 String nunu=(String) names.get(1);
형태로 변경된 것을 확인할 수 있습니다
이는 컴파일 이후에 Generic이 없어지고, Object 형태밖에 추론할 수 없기 때문입니다
Generic 이 나오면 항상 따라 나오는 개념이 있는데요
공변성, 반공변성, 무공변성
공변성, 반공변성, 무공변성 입니다
서로 다른 타입 Type1 과, Type2 가 있을 때,
Something<Type1> Something<Type2> 가 있을 때, 이 2가지 사이의 관계를 의미합니다
무공변성
대부분의 타입입니다. Type1과 Type2의 관계가 어떻든 Something<Type1> Something<Type2> 사이는 관계가 없습니다
실재로 String이 Object의 서브타입임에도, List<Object>에 List<String>을 대입할 수 없는 것처럼 생각할 수 있습니다
공변성
Type1 이 Type2 의 서브타입일 때, Something<Type1> 이 Something<Type2>의 서브타입인 경우를 의미합니다
String이 Object의 서브타입일 때, Object[]에 String[]을 대입할 수 있는 것을 의미합니다
반공변성
Super 에 있는 메서드가 String을 받아들이는데, Sub 의 메서드는 Object를 받아들일 수 있습니다
Object 가 String을 포함하지만, 반대로 Sub가 Super를 포함하는 느낌입니다
extends super
Extends 는 ~~~를 확장한 모든 타입을 받을 수 있다는 내용입니다
Generic 을 통해서 List<Integer> 형태를 List<? extends Integer> 나 List<? extends Object> 에다가 대입할 수 있습니다
당연하지만 ? extends Integer 과 Integer 의 관계는 서브타입인 관계이지만, List<? extends Integer> 과 List<Integer> 은 무공변성이기에, 대입할 수 없습니다
Super 는 ~~~ 의 조상인 모든 타입을 받을 수 있다는 내용입니다
Integer은 Object의 조상이 아니기 떄문에 super 을 했을 때 대입할 수 없습니다
다음 글을 통해서
PESC, VAR ARGS
GENERIC 을 사용하면 안되는 경우
Type Erase 에 대해서 구체적으로 알아보도록 하겠습니다
참조
https://docs.oracle.com/javase/tutorial/java/generics/types.html
'Java' 카테고리의 다른 글
Java 초기화 되지 않음을 표현하는 방법 (0) | 2023.02.27 |
---|---|
Java Generic 딥 다이브 (6) | 2023.02.23 |
java에서 입출력 어디까지 테스트 해야할까요? (2) | 2023.02.19 |
Object 의 toString 부터 hashCode 까지 (0) | 2023.02.19 |
Enum 사용시 메서드 오버라이딩을 주의해서 사용해야 합니다 (0) | 2023.02.17 |