제네릭스

kailyn·2024년 9월 4일

JAVA

목록 보기
10/17

1. 제네릭스

1. 제네릭스(Generics)란?

💡 제네릭은 **데이터의 타입을 일반화한다는 의미**를 가진다. 제네릭스를 활용하는 제네릭 클래스는 제네릭 타입(T, E, K, V)을 활용하여 하나의 클래스로 해당 제네릭 타입에 변화를 줘서 제네릭 클래스의 인스턴스를 다양한 타입을 지닌 인스턴스로 활용할 수 있다.
public class GenericTest<T> {

	private T value;
	
	public T getValue() {
		return value;
	}
	
	public void setValue(T value) {
		this.value = value;
	}
}
// 제네릭 클래스의 T(타입)에 해당하는 부분이 모두 Integer로 변환된다.
GenericTest<Integer> gt = new GenericTest<Integer>();
  • 제네릭스 사용하는 코드
    import com.ohgiraffers.section02.extend.vo.*;
    
    public class Application1 {
        public static void main(String[] args) {
    
            /* 수업목표. extends 키워드를 사용하여 특정 타입만 제네릭 타입으로 사용하도록 제한할 수 있다. */
            /* 설명. Rabbit이거나 Rabbit의 자식 타입이 아닌 타입으로 제네릭 타입을 지정하면 컴파일 에러가 발생한다. */
    //        RabbitFarm<Animal> farm1 = new RabbitFarm<Animal>();
    //        RabbitFarm<Snake> farm2 = new RabbitFarm<Snake>();
    //        RabbitFarm<Mammal> farm3 = new RabbitFarm<Mammal>();
    
            /* 설명. Rabbit 또는 Rabbit의 자식 타입으로는 인스턴스 생성이 가능하다. */
            RabbitFarm<Rabbit> farm4 = new RabbitFarm<>();
            RabbitFarm<Bunny> farm5 = new RabbitFarm<>();
            RabbitFarm<DrunkenRabbit> farm6 = new RabbitFarm<>();
    
            farm4.setAnimal(new Rabbit());
            farm4.getAnimal().cry();
            farm4.setAnimal(new Bunny());
            farm4.getAnimal().cry();                // 동적 바인딩에 의해 반환형인 Animal의 cry()가 아닌 Bunny의 cry()가 실행됨
    
            farm5.setAnimal(new Bunny());
            farm5.getAnimal().cry();
    
            farm6.setAnimal(new DrunkenRabbit());
            farm6.getAnimal().cry();
        }
    
    }
    public class Bunny extends Rabbit{
    
        @Override
        public void cry() {
            System.out.println("바니바니 바니바니 당근당근!");
        }
    }
    public class DrunkenRabbit extends Rabbit{
    
        @Override
        public void cry() {
            System.out.println("봐니봐니 봐니뽜니 당근! 당근! @#%#?!#");
        }
    }
    public class Rabbit extends Mammal {
    
        public void cry() {
            System.out.println("토끼가 울음소리를 냅니다. 끾끾!");
        }
    }

2. 제네릭스를 사용하는 이유

💡 하나의 클래스만 작성해도 여러 타입의 필드 값을 가진 클래스로 변형해서 다룰 수 있어 **구현의 편리함**이 있다. 제네릭을 적용한 클래스는 타입을 명확히 알고 쓰기 때문에 해당 제네릭 클래스의 필드 타입이나 메소드의 매개변수나 반환형을 알고 사용하기 때문에 **자료형의 안전성**이 높다.

2. 와일드 카드

1. 와일드카드(Wildcard)란?

제네릭 클래스의 인스턴스를 유연하게 활용하기 위한 문법. 메소드의 매개변수로 받을 시 타입을 원하는 만큼으로 제한하는 것으로 불특정한 제네릭 클래스 타입을 조금 더 활용할 수 있다.

  • < ? >: 모든 타입을 허용하는 와일드 카드
  • < ? extends T>: T 타입 또는 T의 하위 타입을 허용하는 와일드 카드
  • < ? super T>: T 타입 또는 T의 상위 타입을 허용하는 와일드 카드
  • 와일드카드 사용하는 코드
    import com.ohgiraffers.section02.extend.vo.*;
    
    public class Application2 {
        public static void main(String[] args) {
    
            /* 수업목표. 와일드카드에 대해 이해할 수 있다. */
            WildCardFarm wildCardFarm = new WildCardFarm();
            wildCardFarm.anyType(new RabbitFarm<Rabbit>());
            wildCardFarm.anyType(new RabbitFarm<Bunny>());
            wildCardFarm.anyType(new RabbitFarm<DrunkenRabbit>());
    
            wildCardFarm.extendsType(new RabbitFarm<Bunny>());
    //        wildCardFarm.extendsType(new RabbitFarm<Rabbit>());
    //        wildCardFarm.extendsType(new RabbitFarm<DrunkenRabbit>());
    
            wildCardFarm.superType(new RabbitFarm<Rabbit>());
            wildCardFarm.superType(new RabbitFarm<Bunny>());
    //        wildCardFarm.superType(new RabbitFarm<DrunkenRabbit>());
        }
    }
    import com.ohgiraffers.section02.extend.vo.Bunny;
    import com.ohgiraffers.section02.extend.vo.RabbitFarm;
    
    /* 필기.
     *  와일드카드(wildcard)
     *  제네릭 클래스 타입의 객체를 메소드의 매개변수로 받을 때 타입 변수를 제한할 수 있다.
     *  <?>: 제한 없음
     *  <? extends Type): 와일드카드의 상한 제한(Type과 Type의 후손을 이용해 생성된 제네릭의 인스턴스만 가능)
     *  <? super Type): 와일드카드의 하한 제한(Type과 Type의 부모를 이용해 생성된 제네릭 인스턴스만 가능)
    * */
    public class WildCardFarm {
        /* 설명. 어떤 타입의 RabbitFarm(제네릭 타입)이 와도 상관 없다. */
        public void anyType(RabbitFarm<?> farm) {       // RabbitFarm<T extends Rabbit> 아무나
            farm.getAnimal().cry();
        }
    
        /* 설명. RabbitFarm 중에서도 Bunny 또는 Bunny 하위 타입이 있는 RabbitFarm만 가능(Bunny 제네릭의 농장만 가능) */
        public void extendsType(RabbitFarm<? extends Bunny> farm) {
            farm.getAnimal().cry();
        }
    
        /* 설명. RabbitFarm 중에서도 Bunny 상위 타입이 있는 RabbitFarm만 가능(Bunny이거나 Rabbit 제네릭의 농장만 가능) */
        public void superType(RabbitFarm<? super Bunny> farm) {
            farm.getAnimal().cry();
        }
    }
profile
나는 할 수 있다...!

0개의 댓글