Home [Java] Generics
Post
Cancel

[Java] Generics

Generics란 클래스나 컬렉션 자료구조에 타입 체크를 통해 타입 안정성을 제공해주는 기능이다. 여기서 타입 안정성이란 저장되는 곳에 의도하지 않은 데이터 타입 삽입을 막고 잘못된 형변환의 오류를 방지하는 것을 말한다.

Generics의 필요성


list에 문자열을 저장하고 데이터를 꺼낼때 형변환을 명시해 조회하는 예를 들어보자.

1
2
3
List list = new LinkedList();
list.add("abc"); 
Integer i = (Integer) list.get(0);

이 코드는 String 타입의 데이터를 List에서 값을 꺼낼 때 개발자가 잘못 형변환을 하여 참조변수 i에 Integer 타입으로 형변환하였다. 이는 컴파일시에는 문제가 없이 실행되지만 이 코드를 실행하면 ClassCastException이 발생하게 된다.

1
2
3
4
5
6
7
8
9
10
11
@Test
@DisplayName("Non Generics 타입으로 잘못 형변환하여 데이터를 조회할 시 ClassCastException이 발생한다.")
void NonGenericGetDataTest() {
    List list = new LinkedList();

    list.add("abc");

    Assertions.assertThrows(ClassCastException.class, () -> {
        Integer i = (Integer) list.get(0);
    });
}

이를 방지하고자 JDK1.5버전부터 Generics가 나오게 되고 클래스나 메서드에 Generics 타입으로 선언하게 되면 의도하지 않은 데이터 삽입을 막을 수 있다.

1
2
3
4
5
6
List<String> list = new LinkedList();

list.add(1); // Required type: String, Provided: int

list.add("abc");
Integer i = (Integer) list.get(0); // Inconvertible types; cannot cast 'java.lang.String' to 'java.lang.Integer'

Generics를 사용하여 listString 타입만 다룰 수 있게 선언하게 되면 listint 타입 데이터를 삽입하면 컴파일러가 Required type: String, Provided: int라고 오류를 발생시킨다.

또한 list에서 데이터를 조회할 때 Integer 타입으로 잘못 형변환시키게 되면 Inconvertible types; cannot cast 'java.lang.String' to 'java.lang.Integer'라고 오류가 발생한다.

이렇게 Generics를 사용하면 런타임 때 발생할 오류컴파일 시에 오류를 발생시켜 개발자가 올바르게 코드를 수정할 수 있도록 도와준다.

실제 bytecode로 확인해보면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
@Test
@DisplayName("Generics을 사용한 데이터 조회")
void GenericsTest() {
    List<String> list = new LinkedList();
    list.add("abc");

    String getString = list.get(0);

    Assertions.assertEquals(getString, "abc");
}
1
2
3
4
5
6
7
 L2
    LINENUMBER 32 L2
    ALOAD 1
    ICONST_0
    INVOKEINTERFACE java/util/List.get (I)Ljava/lang/Object; (itf)
    CHECKCAST java/lang/String
    ASTORE 2

아래 코드는 자바의 bytecode 일부분이며 list.get(0)을 수행하면 Object 타입으로 조회되는 데이터를 CHECKCAST 명령어를 통해 String 타입으로 컴파일러가 형변환을 수행해준다. 이 때문에 개발자는 코드로 직접 형변환하는 코드를 작성하지 않아도 됐던 것이다.

이렇게 Generics를 사용하면 컴파일러가 컴파일 시 직접 형변환을 수행해주고 데이터에 대한 타입 체크를 수행해준다.

정리


Generics는 컴파일 타임 때 타입체크를 통해 타입 안정성을 제공해주는 기능이다. Generics의 핵심 개념은 런타임 시 발생하는 ClassCastException을 컴파일 타임으로 끌어와 미리 에러를 발생시켜 코드를 올바르게 수 정할 수 있도록 프로그램 예외 발생을 방지해주는 것이다. 이 개념은 컴파일러의 정적 타입 분석을 이용한 기능이며 Generics컴파일 언어의 특성을 활용한 개념임을 알게 되었다.