소위 제네릭: 클래스와 인터페이스를 정의할 때 유형 매개변수를 지정할 수 있습니다. 이 유형 매개변수는 변수를 선언하고 객체를 생성할 때 결정됩니다(즉, 유형이라고도 할 수 있는 실제 유형 매개변수를 전달합니다). 인수)
일반 클래스 또는 인터페이스
"다이아몬드" 구문
//定义 public interface List<E> extends Collection<E> public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable //使用 List<String> list = new ArrayList(); //Java7以后可以省略后面尖括号的类型参数 List<String> list = new ArrayList<>();
일반 클래스에서 하위 클래스 파생
//方式1 public class App extends GenericType<String> //方式2 public class App<T> extends GenericType<T> //方式3 public class App extends GenericType
의사 일반
실제 일반 클래스는 없습니다. 일반 클래스는 Java 가상 머신에 투명합니다. 즉, JVM은 일반 클래스와 다르지 않게 일반 클래스를 처리합니다. 정적 메서드, 정적 초기화 블록 및 정적 변수에서는 허용되지 않습니다.
- 다음 메소드가 잘못되었습니다.
private static T data; static{ T f; } public static void func(){ T name = 1; }
다음 예는 제네릭 클래스가 없는 것을 측면에서 확인할 수 있습니다
public static void main(String[] args){ List<String> a1 = new ArrayList<>(); List<Integer> a2 = new ArrayList<>(); System.out.println(a1.getClass() == a2.getClass()); System.out.println(a1.getClass()); System.out.println(a2.getClass()); }
Output
true class java.util.ArrayList class java.util.ArrayList
와일드카드 입력
먼저 Foo가 Bar의 부모 클래스이지만 List
다음 방법은 컴파일 오류를 발생시킵니다.
List<?> list = new ArrayList<>(); list.add(new Object());
몇 가지 아이디어:
1. List
2. 배열과 제네릭은 다릅니다. Foo가 Bar의 하위 유형(하위 클래스 또는 하위 인터페이스)이라고 가정하면 Foo[]는 여전히 Bar[]의 하위 유형이지만 G4ee94482edb49d9b25854d5c28f4de2e.
3. 다양한 일반 목록의 상위 클래스를 나타내려면 유형 와일드카드를 사용해야 합니다. 물음표(?)를 목록 컬렉션에 전달하세요. , 쓰기: Listc344555b90c740e0d12635e07ea03035 (알 수 없는 유형의 요소 목록을 의미) 이 물음표(?)를 와일드카드 문자라고 하며 해당 요소 유형은 모든 유형과 일치할 수 있습니다.
와일드카드 문자의 상한
List6e63513cd71e7a5fe3ea6dca3f376865은 모든 SuperType 일반 목록 또는 그 자체의 상위 클래스를 나타냅니다. 와일드카드 상한이 있는 제네릭은 set 메소드를 가질 수 없으며 get 메소드만 가질 수 있습니다.
와일드카드 상한을 설정하면 다음 문제를 해결할 수 있습니다. Dog는 Animal 하위 클래스이고, 들어오는 목록 수를 가져오는 getSize 메서드가 있습니다. 코드는 다음과 같습니다.
abstract class Animal { public abstract void run(); } class Dog extends Animal { public void run() { System.out.println("Dog run"); } } public class App { public static void getSize(List<Animal> list) { System.out.println(list.size()); } public static void main(String[] args) { List<Dog> list = new ArrayList<>(); getSize(list); // 这里编译报错 } }
여기서 프로그래밍 오류가 발생하는 이유는 List4cfe4bcd4d110814d5bcb5b26c812079이 Lista6240277e46d54dc29cc58bc214c4982의 상위 클래스가 아니기 때문입니다. 첫 번째 해결책은 getSize 메소드의 형식 매개변수 List
와일드카드 문자의 하한
List8c2fdd6c4fb4ab3a7453d0a05e326464은 SubType 일반 목록의 하한을 나타냅니다. 와일드카드 상한이 있는 제네릭은 get 메서드를 가질 수 없고 set 메서드만 가질 수 있습니다.
일반 메소드
유형 매개변수를 사용하지 않고 클래스와 인터페이스를 정의하지만 메소드를 정의할 때 유형 매개변수를 직접 정의하려는 경우 JDK1.5에서도 일반 유형 메소드 지원이 가능합니다. . 일반 메소드의 메소드 시그니처에는 일반 메소드의 메소드 시그니처보다 더 많은 유형 매개변수 선언이 있습니다. 유형 매개변수 선언은 쉼표(,)로 구분됩니다. 메소드 수정자 및 메소드 반환 값 유형 구문 형식은 다음과 같습니다.
修饰符 返回值类型 方法名(类形列表){ //方法体 }
일반 메소드를 사용하면 유형 매개변수를 사용하여 메소드의 하나 이상의 매개변수 간 유형 종속성을 표현하거나 반환 간의 메소드 유형 종속성을 표현할 수 있습니다. 값과 매개변수. 이러한 유형 종속성이 없으면 일반 메서드를 사용하면 안 됩니다. 컬렉션의 복사 방법은 일반 방법인
public static <T> void copy(List<? super T> dest, List<? extends T> src){ ...}
를 사용합니다. 이 방법을 사용하려면 src 유형이 dest 유형 또는 그 자체의 하위 클래스여야 합니다.
삭제 및 변환
엄격한 일반 코드에서 일반 선언이 있는 클래스는 항상 유형 매개변수를 전달해야 합니다. 그러나 이전 Java 코드와 일관성을 유지하기 위해 유형 매개변수를 지정하지 않고 일반 선언이 있는 클래스를 사용할 수도 있습니다. 이 제네릭 클래스에 대해 유형 매개변수가 지정되지 않은 경우 유형 매개변수는 원시 유형이라고 하며 매개변수가 선언될 때 지정된 첫 번째 상한 유형이 기본값입니다.
일반 정보가 있는 객체가 일반 정보가 없는 다른 변수에 할당되면 꺾쇠 괄호 사이의 모든 유형 정보가 버려집니다. 예를 들어 List
예제
class Apple<T extends Number> { T size; public Apple() { } public Apple(T size) { this.size = size; } public void setSize(T size) { this.size = size; } public T getSize() { return this.size; } } public class ErasureTest { public static void main(String[] args) { Apple<Integer> a = new Apple<>(6); // ① // a的getSize方法返回Integer对象 Integer as = a.getSize(); // 把a对象赋给Apple变量,丢失尖括号里的类型信息 Apple b = a; // ② // b只知道size的类型是Number Number size1 = b.getSize(); // 下面代码引起编译错误 Integer size2 = b.getSize(); // ③ } }
Java의 제네릭에 대한 자세한 설명과 관련된 더 많은 글은 PHP 중국어 홈페이지를 주목해주세요!