[객체지향프로그래밍][Java] Generics 심화 내용

2023. 6. 3. 17:34·전공/객체지향프로그래밍
728x90
반응형

Generics

제네릭의 사용 이유

컴파일 시간 단축

캐스트의 제거

 

 

Generics class, interface

// raw type Box class
public class Box {
    private Object object;
    public void set(Object object) { this.object = object; }
    public Object get() { return object; }
}

// generic type Box class
public class Box<T> {
    private T t;
    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

클래스 또는 인터페이스의 이름 뒤에 <>를 통해 타입 매개변수를 지정할 수 있음

 

타입 매개변수 예시

E - Element

K - Key

N - Number

T - Type

V - Value

 

예시 1

class Box<T> {
    private T t;
    public T get() { return t; }
    public void set(T t) { this.t = t; }
}

public class Main {
    public static void main(String[] args) {
        Box<String> box1 = new Box<String>();
        box1.set("hello");
        String str = box1.get();
        Box<Integer> box2 = new Box<>(); // type inference 
        box2.set(6);                     // 객체 생성시 타입 매개변수 생략 가능
        int value = box2.get();
    }
}

 

예시 2

class Box<T> { private T t;
    public T get() { return t; }
    public void set(T t) { this.t = t; }
}

interface Pair<K, V> {
    public K getKey();
    public V getValue();
}
class OrderedPair<K, V> implements Pair<K, V> {
    private K key; private V value;
    public OrderedPair(K key, V value) { 
        this.key = key;
        this.value = value;
    }
    public K getKey(){ return key; }
    public V getValue() { return value; }
}
public class Main {
    public static void main(String[] args) {
        Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8);
        Pair<String, String> p2 = new OrderedPair<String, String>("hello", "world"); 
        OrderedPair<String, Integer> p3 = new OrderedPair<>("Even", 8);
        OrderedPair<String, String> p4 = new OrderedPair<>("hello", "world");
        OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>());
                                           // new OrderedPair<>("primes", new Box<>()); 가능
    }
}

 

 

Generics method

<T, R> R method(T t)
ststic <T> void method(T t)
<R> R method(int arg)

위와 같은 형태로 표현

 

예시 1

class Box<T> {
    private T t;

    public <T> T method1(T t) { return this.t = t; } 
    // 제네릭 메소드(O), 메소드의 타입 매개변수 T와 클래스의 T(this.t의 타입)는 다름, 컴파일 에러 
    
    public T method2(T t) { return this.t = t; } 
    // 제네릭 메소드(X)
}

class Box {
    static <T> void method(T t) {...}
    // 제네릭 메소드 (O)
}

 

예시 2

class Util {
    public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
        return p1.getKey().equals(p2.getKey()) &&
                p1.getValue().equals(p2.getValue());
    }

    /* 주석처리된 메소드에 비해 위쪽 제네릭을 사용한 메소드는 다양한 형태의 Pair를 사용할 수 있음
    public static boolean compare(Pair<Integer, String> p1, Pair<Integer, String> p2) {
        return p1.getKey().equals(p2.getKey()) &&  
                p1.getValue().equals(p2.getValue());
    }
    */
}

class Pair<K, V> {
    private K key;
    private V value;

    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }
    
    public void setKey(K key) { this.key = key; }
    public void setValue(V value) { this.value = value; }
    public K getKey() { return key; }
    public V getValue() { return value; }
}

public class Main {
    public static void main(String[] args) {
        Pair<Integer, String> p1 = new Pair<>(1, "apple");
        Pair<Integer, String> p2 = new Pair<>(2, "pear");
        
        boolean same1 = Util.<Integer, String>compare(p1, p2);
        boolean same2 = Util.compare(p1, p2); // type inference
        // 컴파일러가 메소드의 타입 매개변수 형을 추론 가능한 경우
        // 타입 매개변수 형을 명시하지 않아도 됨
        // 대부분의 경우 이렇게 사용
    }
}

 

 

Bounded Type parameters

타입 매개변수의 형태를 한정할 수 있음

 

<U extends Number>

Number를 포함해서 Number를 상속받는 클래스로 U의 범위를 제한

또한 U는 Number를 상속받는 클래스이므로 U.intValue()와 같은 Number의 메소드 사용 가능

(<T>의 경우, 기본적으로 Object를 상속받아 Object의 메소드 사용 가능)

 

인터페이스와 클래스로 타입 매개변수 형태 한정

class A { /* ... */ } 
interface B { /* ... */ } 
interface C { /* ... */ }

// 클래스는 상속이 하나만 가능하므로, 클래스 인터페이스의 순서를 맞춰주어야 함
// class Box extends A implements B, C {}
class D <T extends A & B & C> { /* ... */ }
class D <T extends B & A & C> { /* ... */ } // compile-time error

 

상속과 매개변수 형태 한정

public void boxTest(Box<Number> n) { /* ... */ }

boxTest(new Box<Integer>) // 오류
// Number과 Integer는 상속관계지만
// Box<Number>와 Box<Integer>는 상속 관계가 아님
// 이를 해결하기 위해 와일드카드<?> 개념 도입

 

Wildcards <?>

Box<Number>와 Box<Integer>는 상속 관계 x
Wildcards

List<?> ln = new LinkedList<Number>();
List<?> li = new LinkedList<Integer>();
// 지역변수 선언, 필드 선언, 매개변수 선언에 활용 가능

 

와일드 카드와 서브타입

 

Upper Bounded Wildcards

public class Main {
    public static double sumOfList(List<? extends Number> list) {
        double s = 0.0;
        for (Number n : list)
            s += n.doubleValue();
        return s;
    }

    public static void main(String[] args) {
        List<Integer> li = Arrays.asList(1, 2, 3);
        System.out.println("sum = " + sumOfList(li));
        List<Double> ld = Arrays.asList(1.2, 2.3, 3.5);
        System.out.println("sum = " + sumOfList(ld));
    }
}

 

Lower Bounded Wildcards

public static void addNumbers (List < ? super Integer > list)
{
    for (int i = 1; i <= 10; i++) {
        list.add(i);
    }
}

 

Unbounded Wildcards

public class Main {
    public static void printList(List<?> list) {
        for (Object elem: list)
            System.out.print(elem + " "); System.out.println();
    }
    public static void main(String[] args) {
        List<Integer> li = Arrays.asList(1, 2, 3);
        List<String>  ls = Arrays.asList("one", "two", "three");
        printList(li);
        printList(ls);
    }
}
728x90
반응형

'전공 > 객체지향프로그래밍' 카테고리의 다른 글

[객체지향프로그래밍][Java] Object Cloning  (0) 2023.06.07
[객체지향프로그래밍][Java] Initialization (정적 초기화 블록, 인스턴스 초기화 블록)  (0) 2023.06.07
[객체지향프로그래밍][Java] Queue 심화 내용  (0) 2023.06.01
[객체지향프로그래밍][Java] Set 심화 내용(HashSet, TreeSet)  (0) 2023.06.01
[객체지향프로그래밍][Java] List 심화 내용(Iterator)  (0) 2023.06.01
'전공/객체지향프로그래밍' 카테고리의 다른 글
  • [객체지향프로그래밍][Java] Object Cloning
  • [객체지향프로그래밍][Java] Initialization (정적 초기화 블록, 인스턴스 초기화 블록)
  • [객체지향프로그래밍][Java] Queue 심화 내용
  • [객체지향프로그래밍][Java] Set 심화 내용(HashSet, TreeSet)
dev_ares
dev_ares
대학에서 컴퓨터공학을 전공하고 있는 학생입니다.
    반응형
    250x250
  • dev_ares
    노트
    dev_ares
  • 전체
    오늘
    어제
    • 분류 전체보기 (188)
      • IT 트랜드 (2)
      • 백엔드 (18)
        • Java + Spring (8)
        • Kotlin + Spring (5)
        • 백엔드 (5)
      • 프론트엔드 (1)
        • React (1)
      • 대외활동 (17)
        • 42서울 (17)
      • 백준 (6)
        • Java (2)
        • C++ (3)
      • 전공 (121)
        • 객체지향프로그래밍 (17)
        • 자료구조 (23)
        • 리눅스시스템관리 (16)
        • 컴퓨터구조 (25)
        • 네트워크 (25)
        • 데이터베이스 (15)
        • 기타 전공 (0)
      • 프로그래밍 언어 (18)
        • Java (5)
        • Swift (4)
        • C++ (1)
        • Kotlin (8)
      • 기타 (4)
      • 공군 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    사설 문제
    코틀린
    리눅스
    상속
    컴퓨터구조
    컴공 포트폴리오
    자바
    명령어
    티스토리챌린지
    데이터패스
    메모리 계층 구조
    단일 사이클
    반복자
    추가 문제
    오블완
    C++
    42서울
    컴퓨터 구조 및 설계
    백준
    자료구조
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
dev_ares
[객체지향프로그래밍][Java] Generics 심화 내용
상단으로

티스토리툴바