Java 제네릭(Generics)은 클래스와 인터페이스를 정의할 때 유형 매개변수(Type Parameter)의 사용을 허용하는 JDK5에 도입된 새로운 기능입니다. 선언된 유형 매개변수는 사용 시 특정 유형으로 대체됩니다. 이제 제네릭의 가장 중요한 애플리케이션은 Map 및 List가 사용되는 JDK5의 새로운 컬렉션 클래스 프레임워크입니다. 장점은 자명합니다. 단점은 실제로 장점입니다. 왜냐하면 일반 클래스를 사용할 때 코드의 목적이 매우 명확해야 하고 오류를 사용할 수 없기 때문입니다.
가장 기본적인 제네릭 클래스
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e1;
/**
* 가장 기본적인 제네릭 클래스로, 타입은 직접 정의
* @저자 장가린
*
* @param <T>
*/
공개 클래스 Point<T> {
개인 T var;
공개 T getVar() {
반환 변수;
}
공공 무효 setVar(T var) {
this.var = var;
}
}
패키지 com.garinzhang.javabase.generic.e1;
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
Point<String> p = new Point<String> ();
p.setVar("코더");
System.out.println(p.getVar());
}
}
여러 일반 유형
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e2;
/**
* 일반적으로 S, R 등 T에 가까운 문자를 사용하는 것이 가장 좋습니다.
* @저자 장가린
*
* @param <T>
* @param <S>
*/
공개 클래스 Notepad<T, S> {
개인 T 키;
개인 S 값;
공개 T getKey() {
this.key를 반환합니다.
}
공개 S getValue() {
this.value를 반환합니다.
}
공개 무효 setKey(T 키) {
this.key = 키;
}
공공 무효 setValue(S 값) {
this.value = 값;
}
}
패키지 com.garinzhang.javabase.generic.e2;
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
Notepad<String, Integer> p = new Notepad<String, Integer> ();
p.setKey("코더");
p.setValue(99999);
System.out.println("키: " + p.getKey());
System.out.println("값: " + p.getValue());
}
}
메소드 매개변수에 와일드카드 "?"를 사용하십시오.
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e3;
/**
* 이 예제의 핵심은 main 메소드에 있습니다.
* @저자 장가린
*
* @param <T>
*/
공개 클래스 Info<T> {
개인 T 키;
공개 T getKey() {
this.key를 반환합니다.
}
공개 무효 setKey(T 키) {
this.key = 키;
}
@보수
공개 문자열 toString() {
this.key.toString()을 반환합니다.
}
}
패키지 com.garinzhang.javabase.generic.e3;
/**
* 메소드 매개변수에 와일드카드 사용
* @저자 장가린
*
*/
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
Info<String> i = 새로운 Info<String>();
i.setKey("코더");
재미(i);
Info<Integer> j = new Info<Integer>();
j.setKey(9999);
재미(j);
}
public static void fun(Info<?> temp) {
System.out.println("내용: " + 임시);
}
}
상향 변환 실패
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e4;
/**
* 이 예제의 핵심은 main 메소드에 있습니다.
* @저자 장가린
*
* @param <T>
*/
공개 클래스 Info<T> {
개인 T 키;
공개 T getKey() {
this.key를 반환합니다.
}
공개 무효 setKey(T 키) {
this.key = 키;
}
@보수
공개 문자열 toString() {
this.key.toString()을 반환합니다.
}
}
패키지 com.garinzhang.javabase.generic.e4;
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
Info<String> strEg = 새로운 Info<String>();
Info<Object> objEg;
// 컴파일 오류 "유형 불일치: Info<String>에서 Info<Object>로 변환할 수 없습니다."
//업캐스트 실패, 문자열 -> 객체
// objEg = strEg;
}
}
인터페이스에서 제네릭 사용
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e5;
/**
* 이 예제의 핵심은 main 메소드에 있습니다.
* @저자 장가린
*
* @param <T>
*/
인터페이스 Info<T> {
공개 T getVar();
}
패키지 com.garinzhang.javabase.generic.e5;
/**
* 일반 클래스
* @저자 장가린
*
* @param <T>
*/
공개 클래스 InfoImpl<T>는 Info<T> {를 구현합니다.
개인 T var;
공개 InfoImpl(T var) {
this.setVar(var);
}
공공 무효 setVar(T var) {
this.var = var;
}
공개 T getVar() {
this.var를 반환합니다.
}
}
패키지 com.garinzhang.javabase.generic.e5;
/**
* 제네릭이 아닌 클래스
* @저자 장가린
*
* @param <T>
*/
공개 클래스 InfoImpl1은 Info<String> {를 구현합니다.
개인 문자열 var;
공개 InfoImpl1(문자열 var) {
this.setVar(var);
}
공공 무효 setVar(문자열 var) {
this.var = var;
}
공개 문자열 getVar() {
this.var를 반환합니다.
}
}
패키지 com.garinzhang.javabase.generic.e5;
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
Info<String> strEg = new InfoImpl<String>("coder");
System.out.println("내용: " + strEg.getVar());
Info<String> strEg1 = new InfoImpl1("coder1");
System.out.println("내용: " + strEg1.getVar());
}
}
와일드카드와 확장 및 슈퍼 사용
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e6;
/**
* 이 예제의 핵심은 main 메소드에 있습니다.
* @저자 장가린
*
* @param <T>
*/
공개 클래스 Info<T> {
개인 T 키;
공개 T getKey() {
this.key를 반환합니다.
}
공개 무효 setKey(T 키) {
this.key = 키;
}
@보수
공개 문자열 toString() {
this.key.toString()을 반환합니다.
}
}
패키지 com.garinzhang.javabase.generic.e6;
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
Info<String> strEg = 새로운 Info<String>();
strEg.setKey("코더");
//컴파일 오류 "GenericExample 유형의 fun(Info<? extends Number>) 메서드는 인수(Info<String>)에 적용할 수 없습니다."
// upTypeLimit(i);
// 정수 또는 숫자 유형을 사용합니다.
Info<Integer> intEg = new Info<Integer>();
intEg.setKey(9999);
upTypeLimit(intEg);
//컴파일 오류 "GenericExample 유형의 downTypeLimit(Info<? super String>) 메서드는 인수(Info<Integer>)에 적용할 수 없습니다."
// downTypeLimit(intEg);
// super를 사용하므로 downTypeLimit은 String 자체와 Object만 받을 수 있습니다.
// String의 상속 관계를 확인했는데 다른 클래스는 상속되지 않고 Object만 상속됩니다.
downTypeLimit(strEg);
Info<Object> objEg = 새로운 Info<Object>();
objEg.setKey(999);
downTypeLimit(objEg);
}
/**
* <?extends T>는 유형의 상한을 나타내며, 매개변수화된 유형이 T 또는 T의 하위 클래스일 수 있음을 나타냅니다.
* @param 온도
*/
공개 정적 무효 upTypeLimit(Info<? 확장 번호> 임시) {
System.out.println("내용: " + 임시);
}
/**
* <? super T>는 유형 하한(Java Core에서는 수퍼 유형 자격이라고 함)을 나타내며, 이는 매개변수화된 유형이 Object까지 이 유형의 상위 유형(부모 유형)임을 나타냅니다.
* 이 예에서는 String이 Object에서만 상속되므로 T는 Object 또는 String만 될 수 있음을 의미합니다.
* @param 온도
*/
공개 정적 무효 downTypeLimit(Info<? super String> temp) {
System.out.println("내용: " + 임시);
}
}
메소드 제네릭, 메소드의 여러 제네릭
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e7;
/**
* 메소드 제네릭, 메소드의 여러 제네릭
* @저자 장가린
*
* @param <T>
*/
공개 클래스 정보 {
/**
* 형식 : 메소드 수정 <쉼표로 구분된 형식 목록> 반환값 형식 메소드 이름(파라미터 목록)
* 예: public <T, S> T fun(T t, S s)
* @param t
* @param s
* @반품
*/
공개 <T, S> T fun(T t, S s) {
System.out.println(s.toString());
t를 반환;
}
}
패키지 com.garinzhang.javabase.generic.e7;
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
정보 정보 = 새로운 Info();
String str = info.fun("coder", "두 번째 일반 매개변수 인쇄");
System.out.println(str);
int i = info.fun(30, "두 번째 매개변수를 다시 인쇄합니다.");
System.out.println(i);
}
}
메서드에 전달되거나 반환되는 일반 유형은 메서드가 호출될 때 설정된 매개변수 유형에 따라 결정됩니다.
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e8;
/**
* 연장
* @저자 장가린
*
* @param <T>
*/
공개 클래스 Info<T 확장 번호> {
개인 T var;
공개 T getVar() {
this.var를 반환합니다.
}
공공 무효 setVar(T var) {
this.var = var;
}
@보수
공개 문자열 toString() {
return this.var.toString();
}
}
패키지 com.garinzhang.javabase.generic.e8;
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
Info<Integer> intEg = fun(30); // 여기서 유형은 Integer로 결정되었습니다.
System.out.println(intEg.getVar());
}
/**
* 메소드에 전달되거나 반환되는 일반 유형은 메소드 호출 시 설정된 매개변수 유형에 따라 결정됩니다.
* @param 매개변수
* @반품
*/
public static <T 확장 번호> Info<T> fun(T param) {
Info<T> 임시 = 새로운 Info<T>();
temp.setVar(param);
복귀온도;
}
}
메소드에 전달된 두 매개변수 유형을 일관되게 만드세요.
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e9;
/**
* 메인 보기
* @저자 장가린
*
* @param <T>
*/
공개 클래스 Info<T> {
개인 T var;
공개 T getVar() {
this.var를 반환합니다.
}
공공 무효 setVar(T var) {
this.var = var;
}
@보수
공개 문자열 toString() {
return this.var.toString();
}
}
패키지 com.garinzhang.javabase.generic.e9;
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
Info<String> i1 = 새로운 Info<String>();
i1.setVar("안녕하세요");
Info<String> i2 = 새로운 Info<String>();
i2.setVar("코더");
Info<Integer> i3 = new Info<Integer>();
i3.setVar(999);
추가(i1, i2);
//컴파일 오류 "GenericExample 유형의 add(Info<T>, Info<T>) 메소드는 인수(Info<String>, Info<Integer>)에 적용할 수 없습니다."
// 추가(i1, i3);
}
/**
* 메소드에 전달된 두 매개변수 유형은 일관성이 있어야 합니다.
* @param 매개변수
* @반품
*/
공개 정적 <T> void add(Info<T> i1, Info<T> i2) {
System.out.println(i1.getVar() + ":" + i2.getVar());
}
}
JavaScript의 Arguments 객체와 유사한 제네릭, 변수 매개변수
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e10;
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
정수 i[] = fun(1, 2, 3, 4, 5, 6);
fun2(i);
}
공개 정적 <T> T[] fun(T... arg) {
반환 인수;
}
공개 정적 <T> void fun2(T param[]) {
System.out.println("일반 배열: ");
for(T t : 매개변수) {
System.out.println(t + ",");
}
}
}
일반 중첩: 일반 클래스를 매개변수로 사용하여 반환 값 유형에 따라 반환 값을 결정합니다.
다음과 같이 코드 코드를 복사합니다.
패키지 com.garinzhang.javabase.generic.e11;
/**
* 두 가지 일반 유형을 허용합니다.
* @저자 장가린
*
* @param <T>
*/
공개 클래스 Info<T, V> {
개인 T var;
비공개 V 값;
공개 T getVar() {
this.var를 반환합니다.
}
공공 무효 setVar(T var) {
this.var = var;
}
공개 V getValue(){
this.value를 반환합니다.
}
공공 무효 setValue(V 값) {
this.value = 값;
}
@보수
공개 문자열 toString() {
return this.var.toString();
}
}
패키지 com.garinzhang.javabase.generic.e11;
/**
* 1개의 일반 유형 허용
* @저자 장가린
*
* @param <T>
*/
공개 클래스 데모<S> {
개인 S 정보;
공개 데모(S 정보) {
this.setInfo(info);
}
공공 무효 setInfo(S 정보) {
this.info = 정보;
}
공개 S getInfo() {
this.info를 반환합니다.
}
}
패키지 com.garinzhang.javabase.generic.e11;
java.util.List 가져오기;
com.google.common.collect.Lists 가져오기;
공개 클래스 GenericExample {
/**
* @param 인수
*/
공개 정적 무효 메인(String[] args) {
Demo<Info<String, Integer>> d;
Info<문자열, 정수> i;
i = 새로운 Info<String, Integer>();
i.setVar("코더");
i.setValue(999);
d = 새로운 Demo<Info<String,Integer>>(i);
System.out.println("내용: " + d.getInfo().getVar());
System.out.println("콘텐츠: " + d.getInfo().getValue());
System.out.println(query(1, 2, 3, 4, 5).toString()) // [1, 2, 3, 4, 5]
// 경고 "유형 안전성: varargs 매개변수에 대해 Object&Comparable<?>&Serialized의 일반 배열이 생성되었습니다."
System.out.println(query(1, 2, 3, "StringType").toString()) // [1, 2, 3, StringType]
System.out.println(query("I ", "am ", "a ", "coder").toString());// [I , am , a , coder]
List<String> list = Lists.newArrayList("I", "am", "a", "coder");
System.out.println(list.toString()); // [I , am , a , coder]
}
/**
* 반환 값을 통해 일반 유형을 결정합니다. 이 메소드의 반환 값 유형은 메소드 정의에 의해 자동으로 생성됩니다.
* @param 요소
* @반품
*/
공개 정적 <E> 목록<E> 쿼리(E... 요소) {
// https://github.com/exitsoft/exit-web-framework/commit/1d2f1098a2a4b6abab175b793e2308aa8bd0ea16.
//com.google.common.collect.Lists 가져오기;
// <의존성>
// <groupId>com.google.guava</groupId>
// <artifactId>구아바</artifactId>
// <버전>16.0.1</버전>
// </의존성>
return Lists.newArrayList(elements);
}
}