본문 바로가기
Language/JAVA

[JAVA] 제네릭 1~5 Generic - Data Type

by 아이엠제니 2022. 2. 13.

생활코딩 자바 공부 기록

 

 

1. 제네릭의 사용

제네릭(Generic)은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미함.

나중에서 instance를 생성할 때 확정하는?

제네릭은 data type과 관련이 있다.

class Person<T> {
    public T info;
}

public class GenericDemo {
    public static void main(String[] args) {
        Person<String> p1 = new Person<String>();
        Person<StringBuilder> p2 = new Person<StringBuilder>();
    }    
}

 

 

 

2. 제네릭의 사용이유

class StudentInfo {
    public int grade;

    StudentInfo(int grade) {
        this.grade = grade;
    }
}

class StudentPerson { //중복
    public StudentInfo info;

    StudentPerson(StudentInfo info) {
        this.info = info;
    }
}

class EmployeeInfo {
    public int rank;

    EmployeeInfo(int rank) {
        this.rank = rank;
    }
}

class EmployeePerson { //중복
    public EmployeeInfo info;

    EmployeePerson(EmployeeInfo info) {
        this.info = info;
    }
}

public class GenericDemo {
    public static void main(String[] args) {
        StudentInfo si = new StudentInfo(2);
        StudentPerson sp = new StudentPerson(si);
        System.out.println(sp.info.grade); //2
        EmployeeInfo ei = new EmployeeInfo(1);
        EmployeePerson ep = new EmployeePerson(ei);
        System.out.println(ep.info.rank); //1
    }
}

 

 

 

class StudentInfo {
    public int grade;

    StudentInfo(int grade) {
        this.grade = grade;
    }
}

class EmployeeInfo {
    public int rank;

    EmployeeInfo(int rank) {
        this.rank = rank;
    }
}

class Person { // 코드 중복제거
    public Object info;

    Person(Object info) {
        this.info = info;
    }
}

public class GenericDemo {
    public static void main(String[] args) {
        Person p1 = new Person("부장");
        EmployeeInfo ei = (EmployeeInfo) p1.info;
        System.out.println(ei.rank);
    }
}

컴파일 에러는 발생하지 않지만, 런타임 에러는 발생한다.

 

 

class StudentInfo {
    public int grade;
    StudentInfo(int grade) { this.grade = grade; }
}

class EmployeeInfo {
    public int rank;
    EmployeeInfo(int rank) { this.rank = rank; }
}

class Person<T> { // 코드 중복제거
    public T info;
    Person(T info) { this.info = info; }
}

public class GenericDemo {
    public static void main(String[] args) {
        Person<EmployeeInfo> p1 = new Person<EmployeeInfo>(new EmployeeInfo(1));
        EmployeeInfo ei1 = p1.info;
        System.out.println(ei1.rank); // 성공

        Person<String> p2 = new Person<String>("부장");
        String ei2 = p2.info;
        System.out.println(ei2.rank); //컴파일 실패
    }
}

제네릭화

 

 

 

3. 제네릭의 특징 1

class EmployeeInfo {
    public int rank;

    EmployeeInfo(int rank) {
        this.rank = rank;
    }
}

// 복수의 generic이 필요할 때는 콤마로 구분, 이름이 서로 달라야 한다, 참조형 타입만 올 수 있다
class Person<T, S> {
    public T info;
    public S id;

    Person(T info, S id) {
        this.info = info;
        this.id = id;
    }
}

public class GenericDemo {
    public static void main(String[] args) {
        Integer id = new Integer(1); //wrapper class Integer 생성자로 들어가서 숫자 1을 의미하는 하나의 객체를 instance를 만들었다.
        Person<EmployeeInfo, Integer> p1 = new Person<EmployeeInfo, Integer>(new EmployeeInfo(1), id);
        System.out.println(p1.id.intValue());
    }
}

 

 

 

4. 제네릭의 특징 2 (생략)

제네릭은 생략 가능하다. 

class EmployeeInfo {
    public int rank;

    EmployeeInfo(int rank) {
        this.rank = rank;
    }
}

// 복수의 generic이 필요할 때는 콤마로 구분, 이름이 서로 달라야 한다, 참조형 타입만 올 수 있다
class Person<T, S> {
    public T info;
    public S id;

    Person(T info, S id) {
        this.info = info;
        this.id = id;
    }

    public <U> void printInfo(U info) {
        System.out.println(info);
    }
}

public class GenericDemo {
    public static void main(String[] args) {
        EmployeeInfo e = new EmployeeInfo(1);
        Integer i = new Integer(10);
        Person p1 = new Person(e, i);
        p1.printInfo(e); //제네릭 생략 가능
//        p1.<EmployeeInfo>printInfo(e);
    }
}

 

 

 

5. 제네릭의 제한

abstract class Info {
    public abstract int getLevel();
}

class EmployeeInfo extends Info {
    public int rank;

    EmployeeInfo(int rank) {
        this.rank = rank;
    }

    public int getLevel() {
        return this.rank;
    }
}

class Person<T extends Info> {
    public T info;

    public Person(T info) {
        this.info = info;
    }
}

public class GenericDemo {
    public static void main(String[] args) {
        Person<EmployeeInfo> p1 = new Person<EmployeeInfo>(new EmployeeInfo(1));
//        Person<String> p2 = new Person<String>("부장"); // 컴파일 에러
    }
}

 

 

 

제네릭 1강에서 제네릭의 이용을 보면 이해가 될 것 같은데도,

막상 코드를 보면 긴가민가하다.

일단은 데이터 타입과 관련된 것이라는 것은 알겠음.

보통은 데이터 타입을 정해두고 코드를 작성하지만, 제네릭의 경우 인스턴스화 할 때!

그때 가서 데이터 타입을 결정한다는 것(?)

참조형 타입이 온 다는 것은 알겠지만, int나 double 등 기본타입에 익숙해져 있다가

class가 type으로 올 때면 너무 헷갈린다.

차차 익숙해져야지.

300x250