본문 바로가기

Development/JAVA

(Java) Chapter16. Generic

1. 개념

  - 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법

  - 제네릭 사용의 배경

package chapter_13;
class StudentInfo {
    public int grade;
    StudentInfo(int grade) {this.grade = grade;}
}
//class StudentPerson {               // 아래의 EmployeePerson 과 메커니즘이 같음
//    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;}
//}
class Person1 {
    public Object info;
    Person1(Object info) {this.info = info;}  // 변수의 데이터타입을 지정하는 것은 제한을 두는 것인데 어떠한 데이터타입도 들어올 수 있게 되어버림
}                                             // "부장"도 받아버렸다...
public class _04_Generic2 {
    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 EmployeePerson(ei);
//        EmployeePerson ep = new EmployeePerson(ei);
//        System.out.println(ep.info.rank);       // 1
        Person1 p1 = new Person1("부장");
        EmployeeInfo ei = (EmployeeInfo)p1.info;        // Object 타입, 컴파일 단계에서는 에러가 발생하지 않음 = "type 이 안전하지 않다"
        System.out.println(ei.rank);
    }
}

  - person으로 두 클래스를 통합하려고 할 때 타입이 안전하지 않은 상황이 발생하므로 제네릭을 통해 안전성과 편의성을 도모할 수 있음

2. 제네릭화

package chapter_13;
class EmployeeInfo2 {
    public int rank;
    EmployeeInfo2(int rank) {this.rank = rank;}
}
class Person2 <T, S> {           //  두 개의 제네릭이 사용된 상황, 참조형 데이터타입만 올 수 있다는 제약 있음(그래서 컴파일 단에서 int 가 오류)
    public T info;
    public S id;
    Person2(T info, S id) {      // T = new EmployeeInfo(1), S = 1
        this.info = info;
        this.id = id;
    }
}
public class _05_Generic3 {
    public static void main(String[] args) {
//        Person2<EmployeeInfo, int> p1 = new Person2<EmployeeInfo, int> (new EmployeeInfo(1), 1);
        Integer id = new Integer(1);
        Person2<EmployeeInfo, Integer> p1 = new Person2<EmployeeInfo, Integer> (new EmployeeInfo(1), 1);
        System.out.println(p1.id.intValue());     // 1
    }   // 각각의 기본데이터형들은 wrapper 클래스가 있어서 사용하여 참조형 데이터타입처럼 사용 가능
}

  ※ Integer > int의 참조형 데이터화

 

3. 제네릭의 생략(+ 메소드에 제네릭 적용)

package chapter_13;
class EmployeeInfo3 {
    public int rank;
    EmployeeInfo3(int rank) {this.rank = rank;}
}
class Person3 <T, S> {           //  두 개의 제네릭이 사용된 상황, 참조형 데이터타입만 올 수 있다는 제약 있음(그래서 컴파일 단에서 int 가 오류)
    public T info;
    public S id;
    Person3(T info, S id) {      // T = new EmployeeInfo(1), S = 1
        this.info = info;
        this.id = id;
    }
    public <U> void printInfo(U info) { // 메소드에 제네릭 적용
        System.out.println(info);
    }
}
public class _06_Generic4 {
    public static void main(String[] args) {
        EmployeeInfo e = new EmployeeInfo(1);
        Integer i = new Integer(10);
//        Person3<EmployeeInfo, Integer> p1 = new Person3<EmployeeInfo, Integer> (e, i);
        Person3 p2 = new Person3(e, i); // e와 i라는 매개변수가 제네릭으로 들어갈 수 있다는 것이 당연할 때는 제네릭 생략 가
//        p2.<EmployeeInfo3>printInfo(e);
        p2.printInfo(e);                // 제네릭 생략 가능
    }
}

4. 제네릭의 제한

  1) 배경

    - 클래스가 내부적으로 미정해놓은 어떠한 데이터타입을 인스턴스화 할 때 지정할 수 있는 것. 

    - 문제는 외부에서 무분별한 데이터타입이 유입될 수 있음. 

    - 해결 방법   >   extends, super

  2) extends를 통한 제네릭의 제한

package chapter_13;
abstract class Info {
    public abstract int getLevel();
}
class EmployeeInfo1 extends Info{
    public int rank;
    EmployeeInfo1(int rank) {this.rank = rank;}
    public int getLevel() {
        return this. rank;
    }
}
class Person5<T extends Info>{
    public T info;
    Person5(T info) {
        this.info = info;
    }
}
public class _07_Generic5 {
    public static void main(String[] args) {
        Person5<EmployeeInfo1> p1 = new Person5<>(new EmployeeInfo1(1));
        Person5<String> p2 = new Person5<String>("부정");
    }
}

 

'Development > JAVA' 카테고리의 다른 글

(Java) Chapter15. Reference  (0) 2023.01.29
(Java) Chapter14. enum  (0) 2023.01.29
(Java) Chapter13. Object  (0) 2023.01.23
(Java) Chapter12. 예외  (0) 2023.01.23
(Java) Chapter11. 접근 제어자  (0) 2023.01.17