본문 바로가기
[스파르타코딩클럽]/Java 문법 종합반

Chapter 11. 제네릭(Generic)

by 진진리 2023. 10. 17.
728x90
  • 제네릭의 효용
    1. 중복되거나 필요없는 코드를 줄여줌
    2. 그러면서도 타입 안정성을 해치지 않음

자바에서는 똑같은 로직을 수행하는 함수를 타입을 지정해야 한다는 이유로 여러번 구현해야 함

-> Object를 사용? 이 경우 타입 안정성을 침해받게 됨

-> 단항 연산자를 사용 x. 두 객체의 타입이 다르다면? 로직과 다른 순서의 타입들이 들어오게 된다면? 등등

 

  • 제네릭 문법 예시로 살펴보기
// 1. 2.
public class Generic<T> {
    // 3.
    private T t;
   
    public T get() {
        return this.t;
    }

    public void set(T t) {
        this.t = t;
    }

    public static void main(String[] args) {
	// 4.
        Generic<String> stringGeneric = new Generic<>();
	// 5.
        stringGeneric.set("Hello World");
				
        String tValueTurnOutWithString = stringGeneric.get();

        System.out.println(tValueTurnOutWithString);
    }
}
  1. 제네릭은 클래스 또는 메서드에 사용
  2. 클래스 이름 뒤 <>에 타입 변수를 지정
    • T인 이유는 일종의 컨벤션이기 때문. 그 외 U, V, E 등
  3. 클래스 내에서 특정 타입에 들어갈 자리에 T가 대신 들어갈 수 있음
  4. 타입을 String으로 지정한 객체 생성
  5. 제네릭으로 구현한 클래스 내부의 메소드를 String 타입으로 사용 가능

제네릭 문법

  • 제네릭 용어
public class Generic<T> { ... }

Generic<String> stringGeneric = new Generic<>();
  • 제네릭 클래스: 제네릭을 사용한 클래스
  • T: 타입 변수
  • Generic 클래스를 원시 타입이라고 함

 

  • 제네릭의 제한

1. 객체의 static 멤버에 사용할 수 없음: 타입 변수는 인스턴스 변수로 간주됨

static T get() { ... } // 에러

static void set(T t) { ... } // 에러

2. 제네릭 배열을 생성할 수 없음

 

 

  • 제네릭의 문법

1. 다수의 타입변수 사용 가능

public class Generic<T, U, E> {
    public E multiTypeMethod(T t, U u) { ... }
}

Generic<Long, Integer, String> instance = new Generic();
instance.multiTypeMethod(longVal, intVal);

2. 다형성, 즉 상속과 타입의 관계는 그대로 적용됨

3. 와일드 카드를 통해 제네릭의 제한을 구체적으로 정할 수 있음

public class ParkingLot<T extends Car> { ... }

ParkingLot<BMW> bmwParkingLot = new ParkingLot();
ParkingLot<Iphone> iphoneParkingLot = new ParkingLog(); // error!
  • 와일드 카드
    • <? extends T> : T와 그 자손들만 사용 가능
    • <? super T> : T와 그 조상들만 가능
    • <?> : 제한 없음

4. 메서드를 스코프로 제네릭을 별도로 선언할 수 있음

= 해당 메서드에서만 적용되는 제네릭 변수를 사용할 수 있음

static <T> void sort(List<T> list, Comparator<? super T> c) { ... }
  • 반환 타입 앞에 <> 제네릭을 사용한 경우 해당 메서드에만 적용되는 제네릭 타입 변수 선언
  • 제네릭 클래스의 타입 변수를 static 메서드에서는 사용할 수 없었지만, 이 경우에는 해당 메소드에만 적용되므로 사용 가능
  • 같은 이름의 변수를 사용해도 제네릭 메소드의 타입변수는 제네릭 클래스의 타입변수와 다름
public class Generic<T, U, E> {
		// Generic<T,U,E> 의 T와 아래의 T는 이름만 같을뿐 다른 변수
    static <T> void sort(List<T> list, Comparator<? super T> c) { ... }
}

Collection과 제네릭

  • 리스트: 추상적 자료구조로서, 순서를 가지고 일렬로 나열한 원소들의 모임
    • 검색에는 유리하고 수정/삭제는 불리한 자료구조
    • 리스트의 개념적인 명세는 interface 코드로 구현되어 있음
    • List 인터페이스의 구현체들이 List의 속성을 가지게 됨
    • 제네릭과 함께 List<E> 코드 살펴보기
// 실제 java.util의 List 코드
public interface List<E> extends Collection<E> {
	int size();
	boolean isEmpty();
		...
	boolean addAll(Collection<? extends E> c);
	boolean add(E e);
		...
}

addAll() 메서드의 경우 메서드의 인자는 Collection 타입에 속하면서 List 타입변수 E의 자손 클래스를 원소를 가지고 있어야 함

 

 

'[스파르타코딩클럽] > Java 문법 종합반' 카테고리의 다른 글

Chapter 13. 모던 자바(람다, 스트림, Optional)  (0) 2023.10.18
Chapter 12. 스레드  (0) 2023.10.18
Chapter 10. 예외처리  (0) 2023.10.17
Chapter 9. 인터페이스  (0) 2023.10.17
Chapter 8. 상속  (0) 2023.10.16