제네릭 소개
제네릭이 무엇인지 예를 들어 보겠습니다.
다음과 같이 두 가지 클래스가 있습니다. 두 클래스의 객체를 구성하고 해당 멤버 x를 출력해야 합니다.
public class StringFoo {
private String x
public String getX() {
return x
}
public void setX(String x) {
this.x = x;
}
}
public class DoubleFoo {
private Double x
public Double getX() {
return x; 🎜> public void setX(Double x) {
this.x = x;
}
}
Integer, Long, Date 및 기타 유형에 대한 연산을 구현하려면 쓰기도 필요합니다. 해당 수업은 정말 지루해요.
따라서 위의 두 클래스를 하나의 클래스로 리팩터링하려면 다음 사항을 고려하세요.
위 클래스에서는 멤버와 메서드의 로직은 동일하지만 유형이 다릅니다. Object는 모든 클래스의 상위 클래스이므로 Object를 멤버 유형으로 사용하여 보편적으로 사용할 수 있습니다.
public class ObjectFoo {
private Object x
public Object getX() {
return x
}
public void setX(Object x) {
this.x = x;
}
}
이 호출하는 코드는 다음과 같습니다.
public class ObjectFooDemo {
public static void main(String args[]) {
ObjectFoo strFoo = new ObjectFoo();
strFoo.setX("Hello Generics!");
ObjectFoo douFoo = new ObjectFoo()
douFoo.setX(new Double("33")) ;
ObjectFoo objFoo = new ObjectFoo();
objFoo.setX(new Object())
String str = (String)strFoo.getX(); Double)dou Foo .getX();
객체 obj = objFoo.getX();
System.out.println("strFoo.getX=" + str); ;
System.out.println("strFoo.getX=" + obj);
}
}
위는 제네릭 없이 작성한 내용입니다. 코드는 최상위 기본 클래스 Object를 사용합니다. 타입 선언 후 값을 전달하고, 꺼낼 때 강제 타입 변환을 수행합니다.
JDK는 이러한 문제를 우아하게 해결하기 위해 1.5부터 제네릭 개념을 도입했습니다. 일반 기술을 사용하여 작성된 코드는 다음과 같습니다.
public class GenericsFoo
private T x
public T getX() {
return x; >
public void setX(T x) {
this.x = x;
}
}
호출 코드는 다음과 같습니다.
public class GenericsFooDemo {
public static void main(String args[]){
GenericsFoo
strFoo.setX("Hello Generics!")
GenericsFoo
douFoo.setX(new Double("33");
Object( ))
String str = strFoo.getX(); 🎜> 더블 d = douFoo.getX()
Object obj = objFoo.getX();
System.out.println("strFoo.getX=" + obj);
}
}
몇 가지 명백한 변경 사항이 있습니다.
1. 객체가 생성될 때 GenericsFoo
2. getX 메소드를 통해 객체를 검색하는 경우 유형 변환이 필요하지 않습니다.
3. 각 메서드를 호출할 때 매개 변수 형식이 메서드 생성 시 지정한 형식과 일치하지 않으면 컴파일러에서 오류를 보고합니다.
그렇다면 왜 제네릭이 필요한가요? 두 가지 장점이 있습니다.
1. 컴파일 타임에 저장된 데이터가 올바른지 확인할 수 있습니다. 우리 개발에서는 가능한 한 빨리 오류를 찾는 경향이 있습니다. 가급적이면 Generics는 이 조건을 충족합니다.
2. 강제 변환을 줄입니다. String str = (String)strList.get(0) 이러한 작업은 List에 저장된 객체가 String에 적합하지 않은 경우 상대적으로 위험한 작업입니다. 예외가 발생합니다.
JDK1.5에서는 java.util 패키지의 다양한 데이터 유형 도구 클래스가 프로그래밍에 널리 사용되며 숙달해야 하는 제네릭을 지원합니다.
제네릭의 가장 일반적인 응용 프로그램은 아래에 소개된 클래스, 인터페이스 및 메서드에 있습니다.
3.4.2 일반 사항은 인터페이스에 적용됩니다.
public 인터페이스 ValuePair {
public A getA()
public B getB()
public String toString( ) ;
}
여기서 A와 B는 모두 유형을 나타냅니다. cusp<>에서는 한 가지 유형 또는 여러 유형을 사용할 수 있습니다.
3.4.3 제네릭은 클래스에 적용됩니다.
public class ValuePairImpl {
public final A 먼저
public ValuePairImpl(A a, B; b) { 첫 번째 = a; 두 번째 = b; }
공개 A getA() { 첫 번째 반환 }
공개 B getB() { 두 번째 반환 }
공개 문자열 toString() > Return "(" + first + ", " + second + ")";
}
}
이 클래스가 일반 인터페이스를 구현하는 경우 해당 쓰기 방법은 다음과 같습니다.
public class ValuePairImpl< ,B> ValuePair 구현 {
… .getName() + “ = “ + v.toString()
System.out.println(str); 물론 반환 값은 일반 유형일 수도 있습니다.
3.4.5 사용 가능한 제네릭 유형 제한
위에 소개된 세 가지 제네릭 애플리케이션은 인터페이스, 클래스, 메서드에 적용되며 일반적인 접근 방식이며 전달될 수 있는 유형에 대한 제한이 없습니다. 제네릭으로 제한됩니다. 그러나 일부 시나리오에서는 사용 가능한 유형을 제한하고 싶습니다. 예를 들어, 수신 유형이 특정 클래스에서 상속되어야 합니다(즉, 특정 클래스의 하위 클래스 등이어야 합니다). 경우에는 일반 제한 구문이 사용됩니다.
확장: 일반 유형을 이 유형을 포함하여 특정 클래스의 자손으로 제한합니다.
구문:
여기서 T는 제네릭 유형이고, 확장 키워드는 제네릭 유형을 parentClass의 하위 항목으로 제한합니다. parentClass는 인터페이스일 수도 있는 상위 클래스의 유형을 지정합니다.
Java 언어에서 클래스는 단독으로만 상속될 수 있고 인터페이스는 여러 번 상속될 수 있습니다. 특정 클래스에서 상속하도록 지정된 유형을 제한하고 여러 인터페이스를 구현하려는 경우 구문은 다음과 같습니다.
< ;T는 parentClass & parentInterface1 & parentInterface2>를 확장합니다.
클래스는 인터페이스 앞에 있어야 합니다.
예는 다음과 같습니다.
public class BaseClass {
정수 값;
public BaseClass(int value) {
this.value = value;
}
public int getValue() {
반환 값;
}
public void setValue(int value) {
this.value = value;
}
}
public class SubClass 확장 BaseClass{
public SubClass(int value) {
super(value*2);
}
}
공개 클래스 GenericBound
공개 장기 합계(List
long iValue = 0;
for (BaseClass base : tList) {
iValue += base.getValue();
}
iValue 반환;
}
public static void main(String[] args) {
GenericBound
GenericBound
List
list.add(new SubClass(5));
list.add(new SubClass(6));
System.out.println(obj.sum(list));
}
}
运行,输流结果为22.
接着,我们再深入探讨一下。把상면적例子该写如下:
공개 클래스 GenericBound
공개 장기 합계(List
long iValue = 0;
for (BaseClass base : tList) {
iValue += base.getValue();
}
iValue 반환;
}
public static void main(String[] args) {
// 주의! Class>改为GenericBound
GenericBound
GenericBound
List
list.add(new SubClass(5))
list.add(new SubClass(6))
시스템. (obj.sum(list));
}
}
GenericBound
3.4.6 와일드카드 제네릭
Java의 제네릭 유형은 java.lang.String 및 java.io.File과 같은 일반적인 Java 유형입니다. 예를 들어, 다음 두 변수의 유형은 서로 다릅니다.
Box