ArrayList<String> list = new ArrayList<>();
자바 변수 선언할때 이런형태가 많이 활용되는데 이거에대해서 자세하게 몰라서 한번정리해보려고한다.
위에보이는 꺽쇠괄호가 바로 제네릭이라고한다.
일반 선언문이랑 비교해보면
String[] array = new String[10];
ArrayList<String> array2 = new ArrayList<>(10);
우리가 변수를 선언할때 타입을 정해주듯이, 제네릭은 객체(Object)에 타입을 정해주는것이다.
제네릭은 <>괄호를 사용하는데, 괄호안에 식별자 기호를 지정하여 파라미터화 할 수 있다. 메소드가 파라미터를 받아 사용하는것과 비슷하여 제네릭의 타입매개변수라고 한다.
예시)
class FruitBox<T> {
List<T> fruits = new ArrayList<>();
public void add(T fruit) {
fruits.add(fruit);
}
}
이렇게 클래스명에 제네릭이 들어간것을 볼 수 있다.
이걸 인제 인스턴스화 하면
// 제네릭 타입 매개변수에 정수 타입을 할당
FruitBox<Integer> intBox = new FruitBox<>();
// 제네릭 타입 매개변수에 실수 타입을 할당
FruitBox<Double> intBox = new FruitBox<>();
// 제네릭 타입 매개변수에 문자열 타입을 할당
FruitBox<String> intBox = new FruitBox<>();
// 클래스도 넣어줄 수 있다. (Apple 클래스가 있다고 가정)
FruitBox<Apple> intBox = new FruitBox<Apple>();
이렇게 쓸수 있다.
자바 1.7이후부터는 new생성자부분에 타입을 적어주지않아도 된다고한다.
ArrayList<String> example = new ArrayList<>();
제네릭이 할당받을 수 있는 타입은 Reference타입이다.
int형으로 못받고 Integer형태로 받아야한다.(래퍼클래스와 Reference타입에 대해 찾아봐야겠다.)
제네릭 타입파라미터에 클래스가 들어온다는것은 클래스끼리 상속을 통해 맺은 자식객체도 할당될수 있다.
class Fruit { }
class Apple extends Fruit { }
class Banana extends Fruit { }
class FruitBox<T> {
List<T> fruits = new ArrayList<>();
public void add(T fruit) {
fruits.add(fruit);
}
}
public class Main {
public static void main(String[] args) {
FruitBox<Fruit> box = new FruitBox<>();
// 제네릭 타입은 다형성 원리가 그대로 적용된다.
box.add(new Fruit());
box.add(new Apple());
box.add(new Banana());
}
}
또한 파라미터도 2개이상 들어올 수 있으며, 제네릭안에 제네릭이 들어가도록 중첩해서 쓸 수도 있다.
FruitBox<Apple, Banana> box = new FruitBox<>();
box.add(new Apple(), new Banana());
ArrayList<LinkedList<String>> list = new ArrayList<LinkedList<String>>();
제네릭 사용이유
1. 컴파일시 타입을 검사해 미처 발견하지못한 오류를 방지한다.
2. 불필요한 캐스팅을 없애 성능 향상