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 |