유형 와일드카드
유형 와일드카드는 일반적으로 특정 유형의 실제 매개변수 대신 ?를 사용합니다(여기에는 형식 매개변수가 아닌 유형 실제 매개변수가 있습니다). 타입을 연산할 때 해당 타입의 특정 함수를 사용할 필요가 없고, Object 클래스의 함수만 사용할 경우, ? 와일드카드 문자를 사용하여 알 수 없는 타입을 나타낼 수 있습니다. 예를 들어, List>는 논리적으로 List
public class GenericTest { public static void main(String[] args) { List<String> name = new ArrayList<String>(); List<Integer> age = new ArrayList<Integer>(); List<Number> number = new ArrayList<Number>(); name.add("zwj"); age.add(18); number.add(120); getNumberData(age); // 报错 getNumberData(number); // 120 getData(name); // zwj getData(age); // 18 getData(number); // 120 //getUperNumber(name); // 出现错误,方法中的参数已经限定了参数泛型上限为Number getUperNumber(age); //18 getUperNumber(number); //120 } /** * 在使用List<Number>作为形参的方法中,不能使用List<Ingeter>的实例传入, * 也就是说不能把List<Integer>看作为List<Number>的子类; */ public static void getNumberData(List<Number> data) { System.out.println("data :" + data.get(0)); } /** * 使用类型通配符可以表示同时是List<Integer>和List<Number>的引用类型。 * 类型通配符一般是使用?代替具体的类型实参,注意此处是类型实参; * 和Number、String、Integer一样都是一种实际的类型,可以把?看成所有类型的父类。 */ public static void getData(List<?> data) { System.out.println("data :" + data.get(0)); } /** * 类型通配符上限通过形如List来定义,如此定义就是通配符泛型值接受Number及其下层子类类型。 */ public static void getUperNumber(List<? extends Number> data) { System.out.println("data :" + data.get(0)); } }
제한된 유형 매개변수
때로는 유형 매개변수에 전달될 수 있는 유형의 범위를 제한하고 싶을 때가 있습니다. 예를 들어, 숫자에 대해 작동하는 메서드는 Number의 인스턴스나 Number의 하위 클래스만 허용하기를 원할 수 있습니다. 이때 Monkey는 제네릭 유형에 상한을 추가해야 합니다. 즉, 전달된 유형 인수는 지정된 유형의 하위 유형이어야 합니다.
제한된 유형 매개변수를 선언하려면 먼저 유형 매개변수의 이름을 나열한 다음 확장 또는 슈퍼 키워드를 나열하고 마지막으로 상한 또는 하한을 나열합니다. 이를 통해 제네릭의 상한과 하한의 추가는 제네릭의 선언과 함께 이루어져야 함을 알 수 있습니다.
a7d86c54fd68a52918b9332a3353c71f 는 와일드카드로 표시되는 유형이 T 유형의 하위 클래스임을 나타냅니다. 예를 들어 컬렉션에 요소를 추가할 때 E 유형 개체 또는 E의 하위 유형 개체를 추가할 수 있습니다. 왜? 왜냐하면 E type은 fetch할 때 E class 객체와 E subtype 객체를 모두 받을 수 있기 때문입니다.
117c5a0bdb71ea9a9d0c2b99b03abe3e는 와일드카드로 표시되는 유형이 T 유형의 상위 클래스임을 의미합니다. 예를 들어 작업을 위해 컬렉션에서 요소를 가져올 때 현재 요소의 형식을 사용하여 받거나 현재 요소의 부모 형식을 사용하여 받을 수 있습니다.
public class GenericMethodTest { // 比较三个值并返回最大值 public static <T extends Comparable<T>> T getMaxNuum(T x, T y, T z) { T max = x; // 假设x是初始最大值 if ( y.compareTo( max ) > 0 ){ max = y; //y 更大 } if ( z.compareTo( max ) > 0 ){ max = z; // 现在 z 更大 } return max; // 返回最大对象 } public static void main( String args[] ) { System.out.println( "结果 " + getMaxNuum(3, 4, 5) ); // 结果 5 System.out.println( "结果 " + getMaxNuum(1.2, 6.6, 10.10) ); // 结果 10.10 } }
일반 클래스의 이전 정의를 변경할 수도 있습니다.
public class GenericClassDemo<T extends Number> { private T t; public GenericClassDemo() { } public GenericClassDemo(T t) { this.t = t; } public void setT(T t) { this.t = t; } public T getT(){ return t; } }
이때 GenericClassDemo 일반 클래스를 인스턴스화할 때 매개변수 유형은 Number 및 Number 하위 클래스만 될 수 있습니다. 이를 바탕으로 제네릭 메소드의 예를 살펴보겠습니다.
/** * 在泛型方法中添加上下边界限制的时候, 必须在泛型声明的时候添加; * 也就是在权限修饰符与返回值之间的<T>上添加上下边界 */ public <T extends Number> T getT(GeneriClassDemo<T> demo){ T t = demo.getT(); return t; }
Generic array
자바에서는 정확한 제네릭 타입의 배열을 생성할 수 없습니다.
List<String>[] lsa = new ArrayList<String>[10]; // Not really allowed. Object o = lsa; Object[] oa = (Object[]) o; List<Integer> li = new ArrayList<Integer>(); li.add(new Integer(3)); oa[1] = li; // Unsound, but passes run time store check String s = lsa[1].get(0); // Run-time error: ClassCastException.
이 경우 JVM 일반 삭제 메커니즘으로 인해 JVM은 런타임에 일반 정보를 알지 못하므로 예외 없이 ArrayList를 oa[1]에 할당할 수 있지만 데이터를 가져올 때 유형 변환이 필수인 경우 ClassCastException이 발생합니다. 일반 배열을 선언할 수 있으면 컴파일 중에 경고나 오류가 발생하지 않으며 오류는 런타임에만 발생합니다. 이러한 경우 일반 배열의 선언을 제한하기 위해 컴파일 시 코드에 유형 안전성 문제가 있다는 메시지가 표시될 수 있습니다. 이는 메시지가 전혀 표시되지 않는 것보다 훨씬 낫습니다.
다음 와일드카드 방법이 허용됩니다. 와일드카드 방법을 사용하지 않는 한 배열의 유형은 유형 변수가 될 수 없습니다, 와일드카드 방법의 경우 데이터가 최종적으로 검색될 때 명시적인 유형 변환이 필요하기 때문입니다.
List<?>[] lsa = new List<?>[10]; // OK, array of unbounded wildcard type. Object o = lsa; Object[] oa = (Object[]) o; List<Integer> li = new ArrayList<Integer>(); li.add(new Integer(3)); oa[1] = li; // Correct. Integer i = (Integer) lsa[1].get(0); // OK
관련 기사:
Java의 제네릭에서 T와 물음표(와일드카드)의 차이점
위 내용은 Java의 일반 와일드카드 및 제한 유형 매개변수의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!