Type wildcard
The type wildcard is generally used? instead of the specific type parameter (Here is the type parameter, not the type parameter). When you do not need to use the specific functions of the type when operating a type, but only use the functions in the Object class, you can use the ? wildcard character to represent unknown types. For example, List6b3d0130bba23ae47fe2b8e8cddf0195 is logically the parent class of all Listf4773925085400d671e11357bdd19714 such as Listf7e83be87db5cd2d9a8a0b8117b38cd4, Listc0f559cc8d56b43654fcbe4aa9df7b4a, etc.
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)); } }
Bounded type parameters
Sometimes we want to limit the range of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers may only wish to accept instances of Number or a subclass of Number. At this time, Monkey needs to add an upper bound to the generic, that is, the type argument passed in must be a subtype of the specified type.
To declare a bounded type parameter, first list the name of the type parameter, followed by the extends or super keyword, and finally followed by its upper or lower bound. From this we can know that the addition of the upper and lower bounds of a generic must be together with the declaration of the generic.
d203bb1ae585225d4838a2b7e3d0503e indicates that the type represented by the wildcard is a subclass of the T type. For example, when adding elements to a collection, you can add either an E type object or a subtype object of E. Why? Because when fetching, E type can receive both E class objects and E subtype objects.
117c5a0bdb71ea9a9d0c2b99b03abe3e means that the type represented by the wildcard is the parent class of the T type. For example, when obtaining elements from a collection for operation, you can use the type of the current element to receive it, or you can use the parent type of the current element to receive it.
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 } }
We can also change the previous definition of the generic class:
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; } }
At this time, when instantiating the GenericClassDemo generic class, the parameter type can only be Number and Number subclasses. On this basis, let’s look at an example of a generic method:
/** * 在泛型方法中添加上下边界限制的时候, 必须在泛型声明的时候添加; * 也就是在权限修饰符与返回值之间的<T>上添加上下边界 */ public <T extends Number> T getT(GeneriClassDemo<T> demo){ T t = demo.getT(); return t; }
Generic array
You cannot create an array of an exact generic type in java of.
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.
In this case, due to the JVM generic erasure mechanism, the JVM does not know the generic information at runtime, so you can assign an ArrayList to oa[1] without exception. However, when retrieving data, a type conversion is required, so a ClassCastException will occur. If a generic array can be declared, the above situation will not cause any warnings or errors during compilation. Only when running That's when things go wrong. To limit the declaration of generic arrays, in such cases, you can be prompted at compile time that the code has type safety issues, which is much better than no prompt at all.
The following wildcard methods are allowed: The type of the array cannot be a type variable, unless the wildcard method is used, because for the wildcard method, the final data needs to be retrieved Explicit type conversion.
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
Related articles:
The difference between T and question mark (wildcard) in Java generics
Generics in Java Detailed explanation of type
The above is the detailed content of Generic wildcards and bounded type parameters in Java. For more information, please follow other related articles on the PHP Chinese website!