There are two forms of using wildcard characters in generics: subtype-qualified <? Extends xxx> and super Type limited <? Super xxx>.
(1) Sub-type qualification
The following code defines a pair<t> class, as well as the Employee,manager and President classes.
public class Pair<t> {private T first; Private T second; Public Pair (t first, T second) {this.first = first; This.second = second; } public T GetFirst () {return first; } public T Getsecond () {return second; } public void Setfirst (T newvalue) {first = newvalue; } public void Setsecond (T newvalue) {second = newvalue; }}class Employee {private String name; private double salary; Public Employee (String N, double s) {name = N; Salary = s; } public String GetName () {return name; } public double Getsalary () {return salary; }}class Manager extends Employee {public Manager (String N, double s) {super (n, s); }}<pre name= "code" class= "Java" >class President extends Manager {public president (String N, double s) {s Uper (n, s); }}
Now you want to define a function to print pair<employee>
public static void Printemployeeboddies (Pair<employee> Pair) { System.out.println (Pair.getfirst (). GetName () + ":" + Pair.getsecond (). GetName ()); }
However, one problem is that this function input parameter can only pass type PAIR<EMPLOYEE>, and cannot pass pair<manager> and pair<president>. For example, the following code will generate a compilation error
Manager Mgr1 = new manager ("Jack", 10000.99); Manager MGR2 = new manager ("Tom", 10001.01); pair<manager> Managerpair = new Pair<manager> (MGR1, MGR2); Pairalg.printemployeeboddies (Managerpair);
Compilation errors occur because pair<employee> and pair<manager> are actually two types.
As can be seen, type pair<manager> is type pair<? Extends employee>, so in order to solve this problem, we can change the function definition to
public static void Printemployeeboddies (PAIR<? extends employee> Pair)
But will using wildcards lead to passing pair<? Extends employee> the reference to destroy the Pair<manager> object? For example:
pair<? Extends employee> Employeepair = Managepair;employeepair.setfirst (New Employee ("Tony", 100));
Don't worry, the compiler will generate a compilation error. pair<? After the extends employee> parameter is replaced, we get the following code
? Extends Employee GetFirst ()
void Setfirst (? extends Employee)
For the Get method, no problem, because the compiler knows that the returned object can be converted to an employee type. However, for the set method, the compiler cannot know the specific type, so the call is rejected.
(2) Super type limit
The super-type qualification is the opposite of subtype qualification, which can be supplied to a method, but the return value cannot be used. Super Manager This type is limited to all superclass of manager.
pair<? After the Super manager> parameter is replaced, the following method is obtained
? Super Manager GetFirst ()
void Setfirst (? Super Manager)
The compiler can invoke the Setfirst method with the manager's super type, such as Employee,object, but cannot invoke GetFirst because the manager's superclass reference cannot be converted to a manager reference.
The existence of super-type qualification is to solve the following kind of problem. For example, write a function from manager[] to find the highest and lowest paid two, and put it back in a pair.
public static void Minmaxsal (manager[] Mgrs, pair<? Super Manager> Pair) { if (Mgrs = null | | mgrs.length = = 0) { return; } Pair.setfirst (Mgrs[0]); Pair.setsecond (Mgrs[0]); TODO }
This is how you can call
pair<? Super manager> pair = new pair<employee> (null, NULL); Minmaxsal (new manager[] {mgr1, mgr2}, pair);
(3) <t extends Comparable<? Super t>>
The super type qualification also has a use form: <t extends comparable<? Super t>>
For example, to write a function that returns the smallest object in the array. It seems to be defined as follows.
public static <T> T min (t[] a)
But to find the minimum value must be compared so that T implements the comparable interface. To do this, you can change the method definition to
public static <t extends comparable> T min (t[] a)
Because the comparable interface itself is generic, it can eventually be rewritten as
public static <t extends comparable<t>> T min (t[] a)
But consider the following usage scenarios
Gregoriancalendar[] Birthdays = { new GregorianCalendar (1906, Calendar.december, 9), new GregorianCalendar ( 1815, Calendar.december, ten), new GregorianCalendar (1903, Calendar.december, 3), new GregorianCalendar (1910, Calendar.june, (), }; System.out.println ("Min age =" + arrayalg.min (Birthdays). GetTime ());
Java.util.GregorianCalendar inherits from Java.util.Calendar. GregorianCalendar itself does not implement the comparable interface, its parent class calendar implements the comparable interface.
However, the compiler will error arrayalg.min (birthdays) because GregorianCalendar implements comparable<calendar> instead of comparable< Gregoriancalendar>.
As long as the Min method to change the declaration to <t extends Comparable< Super t>> can be compiled.
The complete method is as follows.
Note that because a class may not implement the comparable method, another method needs to be defined to pass in the comparator object for comparison.
Import Java.util.comparator;public class Arrayalg {public static <t extends comparable<? Super t>> T min ( T[] a) { if (a = = NULL | | a.length = = 0) { return null; } T smallest = a[0]; for (int i = 1; i < a.length; i++) { if (Smallest.compareto (A[i]) > 0) { smallest = A[i]; } } return smallest; } public static <T> T min (t[] A, comparator<? super T> C) { if (a = = NULL | | a.length = = 0) { return n ull; } T smallest = a[0]; for (int i = 1; i < a.length; i++) { if (c.compare (smallest, a[i]) > 0) { smallest = A[i]; } } return smallest;} }
An example of a call to the Min method that passed comparator as a parameter.
manager[] managers = new manager[] { new manager ("Jack", 10000.99), new manager ("Tom", 10001.01), }; Manager minsalmgr = arrayalg.min (managers, new comparator<employee> () { @Override public int Compare ( Employee E1, employee E2) { return Double.compare (E1.getsalary (), e2.getsalary ()); } }); System.out.println ("Min. Salary =" + Minsalmgr.getname ());
This type of parameter is used extensively in Java's class libraries. For example, in the Java.util.Collections class, the following two methods are defined
(4) unqualified wildcard characters? An unqualified wildcard indicates that no type is required. such as pair<?>.
The pair class after the parameter substitution has the following method
? GetFirst ()
void Setfirst (?)
So you can call the GetFirst method because the compiler can convert the return value to object.
However, the Setfirst method cannot be called because the compiler cannot determine the parameter type, which is the fundamental difference between the pair<?> and the pair method.
Unqualified wildcard characters appear to support the following function definitions.
public class Pairalg {public static Boolean hasnulls (Pair<?> p) { return p.getfirst () = = NULL | | p.getsecon D () = = null; }}
java-generic Programming-using wildcard characters? Extends and? Super