제네릭 메소드
- 매개타입과 리턴타입으로 타입파라미터를 갖는 메소드!
public <타입파라미터, ..> 리턴타입 메소드명(매개변수, ...) { }
위와같이 리턴타입과 매개 타입으로 타입 파라미터 <T> 사용한다.
Box<Integer> box = boxing(100);
위와 같은 방식으로 호출이 가능하다. 매개값을 보고 구체적 타입을 추정 가능
public class Util {
public static <T> Box<T> boxing(T t) {
Box<T> box = new Box<T>();
box.set(t);
return box;
}
}
Util 클래스에서 boxing() 정의 후
public class GenericMethodExample {
public static void main(String[] args) {
Box<Integer> box1 = Util.boxing(100);
int intValue = box1.get();
Box<String> box2 = Util.boxing("홍길동");
String strValue = box2.get();
}
}
호출까지!
- Integer 와 String 형식으로 저장하는 코드를 작성하는 것까지!
제한된 타입 파라미터(<T extends 최상위타입>)
- 타입 파라미터에 구체적인 타입을 제한하는 기능
음.. 이렇게 들으면 이게 먼교? 싶겠지만
간단히 말하면 개발자가 원하는 타입만 올 수 있게 제한하는것! 이지 않을까? ㅎㅎ
숫자 연산하는 제네릭 메소드는 곧 넘버타입 혹은 Byte, Short, Integer, Long, Double 타입만을 가져야하는데
이것이 제한된 타입 파라미터라고 한다!
public <T extends 상위타입> 리턴타입 메소드(매개변수, ...) {
}
제한된 타입 파라미터는 이렇게 선언이 가능한데,
여기서 상위타입이란 클래스만이 아니라 인터페이스도 가능하다는거!
public static <T extends Number> int compare(T t1, T t2) {
double v1 = t1.doubleValue();
double v2 = t2.doubleValue();
return Double.compare(v1, v2);
}
doubleValue() 는 넘버 클래스에 정의 되어있는 메소드이며
제공된 넘버 객체들의 숫자를 double타입으로 변환 한다.
여기서!
| <T extends Number>은 매개변수 T가 number 클래스나 하위클래스로 제한된다는 뜻! 그럼 제한 했으니 메서드에 전달되는 것은 넘버클래스나 하위클래스의 인스턴스만 가능하다는것! 또 한가지, Double.compare는 두 더블값을 비교하여 작으면 음수, 같으면 0 크면 1을 반환하는 메서드이다! |
double.compare 메소드는 첫번째 매개값인 v1이 v2보다 작으면 -1 같으면 0 크면 1을 리턴 한다.
실행하게 되면?
public static void main(String[] args) {
// String value = Util.compare("a", "b"); // String은 Number 타입이 아니므로 컴파일 오류 발생
int result1 = Util.compare(1, 2); // int -> Integer (자동 Boxing)
System.out.println(result1);
int result2 = Util.compare(4.5, 3); // double -> Double (자동 Boxing)
System.out.println(result2);
}
주석처리된 String은 당연히 넘버타입이 아니므로 오류 발생할 것이다!
출력값은 -1 1 이 나올것이다!!!
ㅎㅎㅎㅎㅎㅎㅎㅎ 출력값 잘나왔고!!

와일드카드 타입<?>, <? extends …>, <? super ..>
코드에서 ? 를 와일드 카드 (wildcard) 라고 불린다.
구체적인 타입 대신 와일드 카드를 사용 시 3가지 형태로 사용이 가능하다.
1. 제네릭 타입 <?> : 제한없엉 모든 클래스, 인터페이스 타입 가능!
2. 제네릭 타입 < ? extends 상위타입 > : Upper Bounded Wildcards (상위 클래스 제한)
- 타입 파라미터를 대치하는 구체적인 타입으로 상위 타입이나 하위 타입만 올 수 있습니다.
3. 제네릭 타입<? super 하위타입> : Lower Bounded Wildcards (하위 클래스 제한)
- 타입 파라미터를 대치하는 구체적인 타입으로 하위 타입이나 상위 타입이 올 수 있습니다.
예시로 살펴보면!

Course<?>은 수강생의 경우 모든 타입이 가능하다는거!
Course<? extends Student> 은 Student와 하위클래스인 HighStudent 만 가능! extend는 상위클래스를 제한한다했으니!
Course<? super Worker>의 경우는 Worker와 Person만 가능하겠졍? 하위 클래스를 제한한다했으므로~!
위의 그림대로 코드를 작성하면?
- 수강생 타입 4가지 클래스
<Course>
public class Course<T> {
private String name;
private T[] students;
public Course(String name, int capacity) {
this.name = name;
this.students = (T[]) new Object[capacity];
}
public String getName() {
return name;
}
public T[] getStudents() {
return students;
}
public void add(T t) {
for (int i = 0; i < students.length; i++) {
if (students[i] == null) {
students[i] = t;
break;
}
}
}
}
<person>
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
<worker>
public class Worker extends Person {
public Worker(String name) {
super(name);
}
}
<Student>
public class Student extends Person {
public Student(String name) {
super(name);
}
}
<HighStudent>
public class HighStudent extends Student {
public HighStudent(String name) {
super(name);
}
}
<WildCardExample>
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class WildCardExample {
static void registerCourse(Course<?> course) {
System.out.println(course.getName() + " 수강생: " + Arrays.toString(course.getStudents()));
}
static void registerStudentCourse(Course<? extends Student> course) {
System.out.println(course.getName() + " 수강생: " + Arrays.toString(course.getStudents()));
}
static void registerWorkerCourse(Course<? super Worker> course) {
System.out.println(course.getName() + " 수강생: " + Arrays.toString(course.getStudents()));
}
public static void main(String[] args) {
List<Worker> workers = new ArrayList<>();
List<Person> personList = new ArrayList<>();
personList.addAll(workers);
// workers.addAll(personList);
Course<Person> personCourse = new Course<>("일반인과정", 4);
personCourse.add(new Person("일반인"));
personCourse.add(new Worker("직장인"));
personCourse.add(new Student("학생"));
personCourse.add(new HighStudent("고등학생"));
Course<Worker> workerCourse = new Course<>("직장인과정", 4);
workerCourse.add(new Worker("직장인"));
Course<Student> studentCourse = new Course<>("학생과정", 4);
studentCourse.add(new Student("학생"));
studentCourse.add(new HighStudent("고등학생"));
Course<HighStudent> highStudentCourse = new Course<>("고등학생과정", 4);
highStudentCourse.add(new HighStudent("고등학생"));
registerCourse(personCourse);
registerCourse(workerCourse);
registerCourse(studentCourse);
registerCourse(highStudentCourse);
System.out.println("-------------------------");
// registerStudentCourse(personCourse);(X)
// registerStudentCourse(workerCourse);(X)
registerStudentCourse(studentCourse);
registerStudentCourse(highStudentCourse);
System.out.println("-------------------------");
registerWorkerCourse(personCourse);
registerWorkerCourse(workerCourse);
// registerWorkerCourse(studentCourse);(X)
// registerWorkerCourse(highStudentCourse);(X)
}
}
이것의 출력값은?

registerCourse() : 모든 수강생들이 들을 수 있는 과정을 등록하고
registerCourseStudent() : 학생만 들을 수 있는 과정을 등록합니다
registerCourseWorker() : 직장인만 들을 수 있는 과정을 등록합니다.
ㅎㅎㅎㅎㅎ오오!!!! 신기해엽ㅋㅋㅋㅋㅋㅋㅋㅋㅎㅎㅎ

이게진짜 강의를 들으면서 깨달은건데 전 강의도 잘 가르쳐주시긴하지만
독학 체질인가봐요... 이해가 혼자 읽을 때 집중을 좀 더 잘하게 되네요?
음 개념을 강사님께 이미 한번 들어서 그런가 ??ㅎㅎㅎㅎ
역시 복습이 젤 좋은거같다는 생각이 드네요 ㅎㅎㅎ!!!
이 개념의 이해는 된거 같지만 막상 문제가 주어지고
작성을 혼자 하게된다면 ..... ㅎ.... 아마 힘들 거 같다는 생각이... ㅎㅎ
그래도 실습을 열심히 많이 해봐야 느니깐.... !!

제네릭 타입의 상속과 구현
제네릭타입도 다른 타입과 같이 부모클래스가 될 수 있다는거! 그럼 상속이 가능하다는거 ㅎㅎㅎ!!
public class ChildProduct<T, M, C> extends Product<T, M> {
}
이렇게 부모클래스가 될수도 있으며 자식 제네릭타입은 타입 파라미터를 추가로 가질 수도 있다!
상속(inherit)
public class Product<T, M> {
private T kind;
private M model;
public T getKind() {
return kind;
}
public M getModel() {
return model;
}
public void setKind(T kind) {
this.kind = kind;
}
public void setModel(M model) {
this.model = model;
}
}
부모 제네릭 클래스 Product 를
public class ChildProduct<T, M, C> extends Product<T, M> {
private C company;
public C getCompany() {
return this.company;
}
public void setCompany(C company) {
this.company = company;
}
}
ChildProduct가 상속받은 코드 작성해보기!
- 이 코드에서도 부모제네릭클래스에서 상속받고 자식 제네릭 클래스에서 C를 추가한 모습!
구현(implements)
제네릭 클래스가 있다면 제네릭 인터페이스도 존재하겠죵?
public interface Storage<T> {
void add(T item, int index);
T get(int index);
}
Storage<T> 타입을 구현한 StorageImpl 클래스도 제네릭 타입이여야 한다!
코드 작성하면?
public class StorageImpl<T> implements Storage<T> {
private T[] items;
public StorageImpl(int capacity) {
items = (T[]) new Object[capacity];
}
@Override
public void add(T item, int index) {
items[index] = item;
}
@Override
public T get(int index) {
return items[index];
}
}
이렇게 오늘 제네릭에 대해 공부했는데엽!!!
나름 이해는 잘 됐지만 코드 작성연습을 많이 해봐야 늘거 같다는 생각이 드네요 ㅠ
오늘은 데일리 퀴즈 풀고!
sql 자격증 공부하고 자야겠어욤!!!
한번 더 복습하고 싶은데,,, ㅠ 연휴다음날이라 너무 피곤하달까요 ㅠ ㅋㅋㅋ큐ㅠ
자격증은 1달도 안남았으니 자격증 부터 공부할 예정입니다!
오늘도 파이팅했구 !
내일도 파이팅@!!!!!!!!!!!!!!

'[4기] 백엔드 개발자 부트캠프 "오르미" ~ing > [4기] 백엔드 개발자 부트캠프 오르미 수업 복습' 카테고리의 다른 글
| [4기] 45일차 Java ( Collection - list,set ) (0) | 2024.02.15 |
|---|---|
| 일기) DailyQuiz9 (제네릭) (0) | 2024.02.14 |
| [4기] 38일차 Java ( 예외처리3, 제네릭 ) (0) | 2024.02.08 |
| [4기] 37일차 Java ( 예외처리, 트랜잭션 ) (2) | 2024.02.07 |
| [4기] 36일차 Java ( 예외처리 ) (0) | 2024.02.06 |