java

java_chapter12_generics, enumeration, annotation

강용민 2023. 3. 11. 01:03

1. Generics

1.1 Generics란??

지네릭스는 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입체크(compile-time type check)를 해주는 기능이다. 객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어든다.

타입 안정성을 높인다는 것은 의도하지 않은 타입의 객체가 저장되는 것을 막고, 저장된 객체를 꺼내올 때 원래의 타입과 다른 타입으로 잘못 형변환되어 발생할 수 있는 오류를 줄여준 다는 뜻이다.

또한 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해 진다.

 

지네릭스의 용어

class Box<T> {}
  • Box<T> : 지네릭 클래스. 'T의 Box' 또는 'T Box'라고 읽는다.
  • T : 타입 변수 또는 타입 매개변수.(T는 타입 문자)
  • Box : 원시 타입

 

지네릭스의 제한

지네릭스는 인스턴스별로 다르게 동작하도록 하려고 만든 기능이기에 모든 객체에 대해 동일하게 동작해야하는 static멤버에 타입 변수 T를 사용할 수 없다. T는 인스턴스변수로 간주되기 때문이다.

그리고 지네릭 타입의 배열을 생성하는 것도 허용되지 않는다. 지네릭 배열 타입의 참조변수를 선언하는 것은 가능하지만, 'new T[10]'과 같이 배열을 생성하는 것은 안 된다는 뜻이다.

지네릭 배열을 생성할 수 없는 것은 new연산자 떄문인데, 이 연산자는 컴파일 시점에 타입 T가 뭔지 정확히 알아야 한다.

 

1.3 지네릭 클래스의 객체 생성과 사용

class Box<T>{
    ArrayList<T> list = new ArrayList<T>();
    
    void add(T item) {  list.add(item);  }
    T get(int i) {  return list.get(i);  }
    ArrayList<T> getList() {  return list;  }
    int size() {  return list.size();  }
    public String toString() {  return list.toString();  }
 }

 

Box<T>의 객체를 생성할 때는 다음과 같이 한다. 참조변수와 생성자에 대입된 타입(매개 변수화된 타입)이 일치해야 한다. 일치하지 않으면 에러가 발생한다.이는 두 타입이 상속관계에 있어도 마찬가지이다.

단, 두 지네릭 클래스의 타입이 상속관계에 있고, 대입된 타입이 같은 것은 괜찮다.

 

1.4 제한된 지네릭 클래스

타입 문자로 사용할 타입을 명시하면 한 종류의 타입만 저장할 수 있도록 제한할 수 있지만, 그래도 여전히 모든 종류의 타입을 지정할 수있다는 것에는 변함이 없다. 그렇다면, 타입 매개변수 T에 지정할 수 있는 타입의 종류를 제한하려면 어떻게 해야할까??

class FruitBox<T extends Fruit> { //Fruit의 자손만 타입으로 지정가능
    ArrayList<T> list = new ArrayList<T>();
    ...
}

다음과 같이 지네릭 타입에 'extends'를 사용하면 특정 타입의 자손들만 대입할 수 있게 제한할 수 있다. 이는 인터페이스에도 적용된다.

 

1.5 와일드 카드

만약 오버로딩을 다음과 같이 한다면 어떻게 될까??

static Juice makeJuice(FruitBox<Fruit> box) {
    String tmp = "";
    for(Fruit f : box.getList()) temp += f + " ";
    return new Juice(tmp);
}

static Juice makeJuice(FruitBox<Apple> box) {
    String tmp = "";
    for(Fruit f : box.getList()) temp += f + " ";
    return new Juice(tmp);
}

지네릭 타입이 다른 것만으로는 오버로딩이 성립하지 않기 때문에 컴파일 에러가 발생한다. 이럴때 사용하기 위해 곡안된 것이 바로 '와일드 카드'이다.

  • <? extends T> : 와일드 카드의 상한 제한. T와 그 자손들만 가능
  • <? super T> : 와일드 카드의 하한 제한. T와 그 조상들만 가능
  • <?> : 제한 없음. 모든 타입이 가능 <? extends Object>와 동일

문제

1. Generics의 장점은 어떤 것이 있나??

- 타입 안정성을 제공한다.

- 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해 진다.


2. 열거형(enums)

2.1 열거형이란?

열거형은 서로 관련된 상수를 편리하게 선언하기 위한 것으로 여러 상수를 정의할 때 사용하면 유용하다.

 

2.2 열거형의 정의와 사용

enum 열거형이름 { 상수명1, 상수명2, ...}

 

 

 

 

 

 

'java' 카테고리의 다른 글

java_chapter14_람다와 스트림  (0) 2023.03.13
java_chapter13_쓰레드  (0) 2023.03.11
java_Chapter08_예외처리  (0) 2023.03.10
Java_Chapter08_객체 지향 4대 요소  (0) 2022.10.09
Java_Chapter?_builder pattern  (0) 2022.10.06