Java

[Java] 자바 제네릭스 (Generics)

공대생안씨 2024. 7. 28. 22:48

1. 제네릭스 (Generics)

  • 결정되지 않은 타입을 타입 변수로 처리
  • 실제 사용할 때는 구체적인 타입으로 대체
  • 예시) 커피에서 컵은 커피 담는 용도 / 내가 따로 구매한 컵은 물을 담을 수도, 연필을 꽂을 수도 있음 ⇒ 제네릭 타입 사용하면 그때그때 필요한 타입을 개발자가 정해서 생성 가능!
  • 컴파일 단계에서 자료형을 체크해주는 도구코드 안정성 더해줌!
public class GenericClass<T> {

    T ob;
    
    public GenericClass(T ob) {
        this.ob = ob;
    }
	
    public void printType() {
        System.out.println(ob.getClass().getName());
    }
}

class GenericClass2<T, V> {

    T ob;
    V ob2;
	
    public GenericClass(T ob, V ob2) {
        this.ob = ob;
        this.ob2 = ob2;
    }
	
    public void printType() {
        System.out.println("ob type: " + ob.getClass().getName());
        System.out.println("ob2 type: " + ob2.getClass().getName());
    }
}

class Main {
    public static void main(String[] args) {
		
        GenericClass<Integer> generic1 = new GenericClass<>(100);
        generic1.printType();
		
        GenericClass<Double> generic2 = new GenericClass<>(3.14);
        generic2.printType();
		
        GenericClass2<String, Long> generic3 = new GenericClass2<>("Hello", 10L);
        generic3.printType();
    }
}

/* 실행결과
java.lang.Integer
java.lang.Double
ob type: java.lang.String
ob2 type: java.lang.Long
*/

 

1-1. 제네릭 사용 예제

import java.util.ArrayList;

public class Box <T>{
    private ArrayList<T> data = new ArrayList<>();

    public void addData(T data) {
        this.data.add(data);
    }

    public ArrayList<T> getData() {
        return this.data;
    }
}

class Book {
    String name;
    String author;

    public Book(String name, String author) {
        this.name = name;
        this.author = author;
    }

    public void printInfo() {
        System.out.println("name = " + name);
        System.out.println("author = " + author);
    }
}

class Account {
    String name;
    int amount;

    public Account(String name, int amount) {
        this.name = name;
        this.amount = amount;
    }

    public void printInfo() {
        System.out.println("name = " + name);
        System.out.println("author = " + amount);
    }
}

class GenericMain {
    public static void main(String[] args) {
        Box<Book> bookBox = new Box<>();
        bookBox.addData(new Book("자바", "김영철"));
        bookBox.addData(new Book("자바2", "홍길동"));
        // 이미 bookBox 타입이 Book으로 정해졌으므로 다른 클래스의 인스턴스는 넣을 수 없음
        // bookBox.addData(new Account("신한", 10000));
        System.out.println("bookBox = " + bookBox);
        ArrayList<Book> data = bookBox.getData();
        for (Book book : data) {
            System.out.println("book = " + book);
            book.printInfo();
        }
        System.out.println("===============================");
        Box<Account> accountBox = new Box<>();
        accountBox.addData(new Account("신한", 1000));
        accountBox.addData(new Account("농협", 99999999));
        System.out.println("accountBox = " + accountBox);
        ArrayList<Account> data1 = accountBox.getData();
        for (Account account : data1) {
            System.out.println("account = " + account);
            account.printInfo();
        }

    }
}

/* 실행결과
bookBox = week3.ch3_2.generics.Box@30f39991
book = week3.ch3_2.generics.Book@452b3a41
name = 자바
author = 김영철
book = week3.ch3_2.generics.Book@4a574795
name = 자바2
author = 홍길동
===============================
accountBox = week3.ch3_2.generics.Box@23fc625e
account = week3.ch3_2.generics.Account@3f99bd52
name = 신한
author = 1000
account = week3.ch3_2.generics.Account@65b54208
name = 농협
author = 99999999
*/

 

  • <?> : 타입에 제한 거는 것
List<?> unbound = new ArrayList<>();
// Integer 를 상속받은 타입만!
List<? extends Integer> upperBounded = new ArrayList<>();
// Integer의 부모 타입만!
List<? super Integer> lowerBounded = new ArrayList<>();