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<스트링(영어로)>; <= 안된다.
      • 오브젝트를 담을 수 있는데 스트링이라고 한정하면 나머지를 담지 못하기 때문에 오류가 뜬다.
      • 오브젝트의 자식 클래스를 지정하면 안된다.

레퍼런스를 선언할 때

  • 제네릭의 타입을 지정하지 않으면 다양한 종류의 어레이리스트를 파라미터로 넘길 수 있다.
  • 그러므로 레퍼런스를 선언할 때 제대로 제네릭의 타입을 지정해야 한다.

제네릭 결정 불가할 때

  • 컴파일러는 파라미터로 받은 어레이리스트가 어떤 타입의 값을 다루는지 알 수 없기 때문에 그 타입인지 검사해야 하는 메서드를 사용할 때는 컴파일을 명확하게 해줄 수 없다. 따라서 컴파일 오류를 발생시킨다.

Categories:

Updated: