2020-09-01 TIL
2 minute read
제네릭
- 제네릭 문법이 없다면 각 타입의 객체를 저장하기 위해 각 타입에 대한 클래스를 정의해야 한다.
- 제네릭 문법은 코드의 안정성을 추구한다.
- 원하는 타입이 아닌 다른 타입의 값을 지정하는 오류를 막기 위해 만들어졌다.
- 각 객체 타입 별로 클래스를 생성해야 하면 타입 별로 만들어야 할 클래스가 무한정으로 늘어난다.
- 같은 일을 하는 클래스임에도 불구하고 다루는 객체의 타입이 다르다는 이유만으로 여러개의 유사 클래스를 반복적으로 정의해야 하는 문제가 생긴다.
- 해결책으로 다형적 변수의 특징을 이용하여 값을 저장하는 인스턴스 변수 오브젝트 타입으로 정의한다.
- 인스턴스 변수를 오브젝트로 선언하면 한 개의 클래스만 정의하면 된다.
- 객체의 타입 별로 클래스를 구분해서 쓰지 않으니 코딩이 편하지만 값을 꺼낼 때마다 원래의 타입으로 바꾸기 위해 형변환을 해야한다.
- 오브젝트 타입이기 때문에 원래의 목적과 다른 객체를 넣어도 오류를 띄우지 않는다는 문제점이 있다.
- 제네릭 문법은 컴파일러를 대상으로 한다.
다형적 변수의 한계(문제점)를 극복하기 위해 제네릭을 사용한다.
- 한 개의 클래스가 다양한 타입의 객체를 제한적으로 다루게 만든다.
- 클래스의 레퍼런스를 정의할 때 어떤 타입의 값을 다룰 것인지 제한을 걸아야 한다.(변수 타입 지정)
- 인스턴스를 생성할 때도 어떤 타입의 값을 다룰 것인지 지정해야 한다.
- 객체를 생성할 때 타입 지정을 생략할 수 있다.
- 메서드를 사용할 때 그 타입 전용 클래스인 것처럼 쓰면 되고 형변환을 할 필요가 없다.
제네릭으로 사용하는 변수 이름 종류
- 자바에서 제안하는 변수 이름은 다음과 같다.
- T - type
- E - element
- K - key
- V - value
- N - number
- 여러개의 파라미터를 쓸 때는 보통 두 번째 파라미터부터 다음 알파벳을 사용한다.
특징
- 지정한 타입 전용 클래스로 동작한다.
- 그래서 타입이 아닌 경우 메서드를 호출할 수 없다.
- 제네릭 문법을 사용하면 오브젝트 타입을 사용하는 것보다 편리하다.
- 각 타입별로 클래스를 지정하는 듯한 효과가 있다.
제네릭 사용
- 특징 1 : 다루는 타입을 제한할 수 있다.
- 즉, 어레이리스트가 어떤 종류(타입, 클래스)의 객체를 저장할 것인지 지정할 수 있다.
- 지정된 타입 외의 객체는 저장할 수 없다.
- 사용법 : 클래스명<타입명>타입명>
- 특징 2 : 제네릭을 지정하면 그와 관련된 메서드의 타입 정보가 자동으로 바뀐다.
- 형변환하는 번거로움이 없다.
- 제네릭이 없다면 값을 꺼낼 때마다 형변환을 해줘야 한다.
- 아니면 값의 종류별로 어레이리스트를 만들어야 한다.
- 제네릭 문법이 존재하므로 한 개의 클래스로 형변환 없이 특정 타입 전용 클래스를 만들 수 있다.
생략
- 레퍼런스를 선언할 때는 타입명을 생략하면 안된다.
- ArrayList list; => ArrayList<?> list;
- 어떤 타입이든 넣을 수 있다.
- 바람직하지 않기 때문에 경고가 뜬다.
- ArrayList<?> list;
- 이것 역시 바람직하지 않기 때문에 경고가 뜬다.
- ArrayList<오브젝트(영어로)> list;
- ArrayList<오브젝트(영어로)>로 만든 객체는 Object의 모든 객체를 담을 수 있다.
- list.add(new String()); <= 된다.
- add 할때는 오브젝트의 자식들을 담을 수 있다.
- list = new ArrayList<스트링(영어로)>; <= 안된다.
- 오브젝트를 담을 수 있는데 스트링이라고 한정하면 나머지를 담지 못하기 때문에 오류가 뜬다.
- 오브젝트의 자식 클래스를 지정하면 안된다.
레퍼런스를 선언할 때
- 제네릭의 타입을 지정하지 않으면 다양한 종류의 어레이리스트를 파라미터로 넘길 수 있다.
- 그러므로 레퍼런스를 선언할 때 제대로 제네릭의 타입을 지정해야 한다.
제네릭 결정 불가할 때
- 컴파일러는 파라미터로 받은 어레이리스트가 어떤 타입의 값을 다루는지 알 수 없기 때문에 그 타입인지 검사해야 하는 메서드를 사용할 때는 컴파일을 명확하게 해줄 수 없다. 따라서 컴파일 오류를 발생시킨다.