https://butter-shower.tistory.com/88
[Java] 제네릭 프로그래밍
제네릭 프로그래밍(Generic Programming) 이란? 작성한 코드를 다양한 타입의 객체에 대해 재사용한다는 객체 지향 기법이다. 제네릭(Generic) : 클래스를 정의할 때 구체적인 타입을 적지 않고 변수 형
butter-shower.tistory.com
자바 제네릭 프로그래밍
제네릭 프로그래밍이란?
- 작성한 코드를 다양한 타입의 객체에 대해 재사용 한다는 객체 지향 기법입니다.
- 제네릭 (Generic) : 클래스를 정의할 때 구체적인 타입을 적지 않고 변수 형태로 적어 놓는 것입니다. 객체를 생성할 때 구체적인 타입을 기재합니다.
제네릭 클래스 설계
1. 선언
class 클래스이름<타입매개변수> {
// 메서드나 필드에 필요한 타입을 타입 매개변수로 나타낸다.
필드;
메서드;
}
- 타입 매개변수는 객체를 생성할 때 구체적인 타입으로 대체합니다.
2. 전형적인 타입 매개변수
타입 매개변수 | 설명 |
E | 원소 (Element) |
K | 키 (Key) |
N | 숫자 (Number) |
T | 타입 (Type) |
V | 값 (Value) |
3. 제네릭 객체 생성
-
제네릭클래스 <적용할타입> 변수 = new 제네릭클래스<적용할타입>(); |_ 생략 가능
제네릭의 제약
- 기초 타입을 제네릭 인수로 사용 불가
- 정적 제네릭 타입 금지
- 제네릭 타입의 인스턴스화 금지. 즉, new T() 등 금지
- 제네릭 타입의 배열 생성 금지
- 실행 시간에 제네릭 타입 점검 금지
예를 들어, a instance of ArrayList<String> - 제네릭 클래스의 객체는 예외로 던지거나 잡을 수 없음
- 제네릭의 서브타입 허용 않음
제네릭 메서드
1. 의미와 선언 방법
- 타입 매개변수를 사용하는 메서드
- 제네릭 클래스 뿐만 아니라 일반 클래스의 멤버도 될 수 있음
- 제네릭 메서드를 정의할 때는 타입 매개변수를 반환 타입 앞에 위치
- 제네릭 메서드를 호출할 때는 구체적인 타입 생략 가능 -> 다이아몬드 연산자 : <>
- JDK7과 JDK8의 경우 익명 내부 클래스에서는 다이아몬드 연산자 사용 불가
- JDK9부터 익명 내부 클래스에서도 다이아몬드 연산자 사용 가능
2. 정의와 호출 방법
class InstanceTypeShower {
int showCount = 0;
public <T> void showInstanceType(T ins) {
System.out.println(ins);
showCount++;
}
void showPrintCount() { ... }
}
public static void main(String[] args) {
AAA aaa = new AAA();
BBB bbb = new BBB();
InstanceTypeShower shower = new InstanceTypeShower();
shower.<AAA>showInstanceType(aaa);
shower.<BBB>showInstanceType(bbb);
shower.showPrintCount();
}
- 제네릭 메서드의 호출과정에서 전달되는 인자를 통해서 제네릭 자료형을 결정할 수 있으므로 자료형 표현 생략 가능합니다.
3. 제네릭 메서드와 둘 이상의 자료형
class InstanceTypeShower2 {
public <T, U> void showInstanceType (T instance1, U instance2) {
System.out.println(instance1);
System.out.println(instance2);
}
}
- T, U와 같은 문자는 상징적입니다. 따라서 타 문자로도 대체 가능합니다.
public static void main(String[] args) {
AAA aaa = new AAA();
BBB bbb = new BBB();
InstanceTypeShower2 shower = new InstanceTypeShower2();
shower.<AAA, BBB>showInstanceType(aaa, bbb);
shower.showInstanceType(aaa, bbb);
}
- 마찬가지로 메서드 호출 시, 자료형의 정보는 생략 가능합니다.
제한된 타입의 제네릭 메서드
1. 제네릭 타입에 대한 범위 제한
- 사용 방법
-
<T extends 특정 클래스 혹은 인터페이스> 반환타입 메서드이름(...){...}
- T가 상속 또는 구현하는 클래스의 자료형이 되어야 함을 명시합니다.
- 주의 : 부모 인터페이스인 경우도 implements가 아니라 extends를 사용합니다.
-
public static <T extends UpperClass> void showInstanceANcestor (T param) { param.showYourAncestor(); }
-
public static <T extends SimpleInterface> void showInstanceName (T param) { param.showYourName(); }
-
제한된 메서드와 배열
1. 제네릭 메서드로의 배열 전달
- 배열도 인스턴스이므로 제네릭 매개변수에 전달 가능합니다.
- 하지만 이렇게 전달을 하면 다음과 같은 문장을 쓸 수 없습니다.
-
System.out.println(arr[i]);
-
- 다음과 같이 매개변수를 선언하면, 매개변수에 전달되는 참조값을 배열 인스턴스의 참조값으로 제한할 수 있습니다.
-
T[] arr
-
- 이렇게 선언하면 참조 값을 배열 인스턴스의 참조 값임이 보장되므로 [] 연산을 허용합니다.
-
public static <T> void showArrayData(T[] arr) { for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } }
- [] 연산이 필요하다면 매개변수의 선언을 통해서 전달되는 참조 값을 배열의 참조 값으로 제한해야 합니다.
-
와일드 카드 타입
1. 제네릭타입<?> : Unbounded wildcards (제한 없음)
2. 제넥릭타입<? extends 상위 타입>
- Upper Bounded Wildcards (상위 클래스 제한)
- 상위 타입을 상속하는 클래스의 인스턴스라면 무엇이든지 참조 가능
3. 제네릭타입<? super 하위 타입>
- Lower Bounded Wildcards (하위 클래스 제한)
- 하위 타입이 상속하는 클래스의 인스턴스라면 무엇이든지 참조 가능
제네릭 클래스의 상속
1. 타입 파라미터는 자식 클래스에도 기술해야 함
-
public class ChildProduct<T, M> extends Product<T,M> {...}
- 인스턴스 생성 시 자료형 지정
-
ChildProduct<String, String> myChild = new ChildProduct<String, String>(); ChildProduct<Integer, Integer> myChild = new ChildProduct<Integer, Integer>();
-
2. 추가적인 타입 파라미터를 가질 수 있음
public class ChildProduct<T, M, C> extends Product<T, M> {...}
3. 제네릭 클래스의 자료형을 결정해서 상속하는 것도 가능
public class ChildProduct extends Product<String, Integer> {...}
제네릭 타입의 구현
1. 제네릭 인터페이스를 구현할 경우, 제네릭 인터페이스를 구현한 클래스도 제네릭
- 제네릭 인터페이스를 구현할 경우, 제네릭 인터페이스를 구현한 클래스도 제네릭
-
제네릭 인터페이스interface MyInterface<T> { public T myFunction(T item); }
-
제네릭 인터페이스 구현 모델, 일반적인 인터페이스의 구현과 같습니다.class MyImplement<T> implements MyInterface<T> { public T myFunction(T item) { return item; } }
-
제네릭 인터페이스 구현 모델, 제네릭 인터페이스의 자료형을 지정해서 구현하는 것도 가능합니다.class MyImplement implements MyInterface<String> { public T myFunction(String item) { return item; } }
-
'JAVA' 카테고리의 다른 글
[JAVA] - 문자열 치환 메서드 (replace, replaceAll, replaceFirst) (0) | 2024.07.18 |
---|---|
[JAVA] - List의 요소 위치 바꾸기 (swap) (2) | 2024.07.16 |
[JAVA] - BigInteger & BigDecimal 사용법 및 정리 (1) | 2024.06.04 |
[JAVA] - indexOf, lastIndexOf 특정 문자 위치 찾기 (0) | 2024.05.31 |
[JAVA] - Stream API 이해 6 (0) | 2024.05.31 |