[Java Foundation]java Wildcard

Source: Internet
Author: User
Tags comparable object object

Transferred from: http://peiquan.blog.51cto.com/7518552/1303768

I thought this would be a relatively basic blog, but once we delve into it, I find a lot of interesting things and a lot of confusing places. Wildcards are an interesting thing, and if you do, you'll make your code more generic (more robust). First of all, this article is based on the Java generics, if you are not familiar with generics, you can click here . In order to understand the wildcard character more thoroughly, define the following classes.

public class Animal {private string name;public Animal (String name) {this.name = name;} public void Eat () {System.out.println (GetName () + "can eat."); Public String GetName () {return name;}}

public class Cat extends Animal {public Cat (String name) {super (name);} public void Jump () {System.out.println (GetName () + ' can jump. ');}}

public class Bird extends Animal {public Bird (String name) {super (name);} public void Fly () {System.out.println (GetName () + "can fly.");}}

public class Magpie extends Bird {public Magpie (String name) {super (name);} public void Sing () {System.out.println (GetName () + ' can not ' only eat,but sing ');}}


First, let's take a look at examples of the use of wildcard characters, as follows:

public class Animaltrainer {public void Act (list<animal> List) {for (Animal animal:list) {animal.eat ();}}}

The test code is as follows:

public class Testanimal {public static void main (string[] args) {Animaltrainer Animaltrainer = new Animaltrainer ();//test 1list<animal> animallist = new arraylist<> (), Animallist.add (New Cat ("CAT1")), Animallist.add (New Bird (" Bird1 ")); Animaltrainer.act (animallist);//Can be compiled//test 2list<cat> catlist = new arraylist<> (); Catlist.add (New Cat ("CAT2")), Catlist.add (New Cat ("CAT3")), Animaltrainer.act (catlist);//Cannot be compiled}}

As above, the execution of Test 1 should be understandable, but incidentally, because CAT1 and Bird1 are Animal objects, can naturally be added list<animal>, the specific explanation can refer to the Java Generic Foundation . For Test 2, it is not possible to compile because list<cat> is not a list<animal> subclass, and the incoming parameters are wrong and cannot be compiled. Now try to modify the Animaltrainer.act () code to make it more generic, not just to accept the list<animal> parameter, but also to accept parameters such as list<bird>. How does that change??

First, the upper bound of a wildcard character

Since it is known that list<cat> is not a list<anilmal> subtype, it is necessary to find a solution for him, that is, the Animaltrianer.act () method becomes more general (acceptable list<animal > can accept list<cat> and other parameters). The solution in Java is to use the wildcard character "? ", specifically to Animaltrianer, is to change the method to act (LIST< Extends Animal> list), among them "? "is a wildcard, and"? Extends Animal "is a wildcard?" "The upper bound is animal, in other words,"? Extends Animal "can represent Animal or its subclasses, and can not represent Animal's parent class (such as Object) because the upper bound of the wildcard is Animal. As below, for the improvement after the Animaltrianer

public class Animaltrainer {public void Act (LIST<. extends animal> List) {for (Animal animal:list) {animal.eat ();} }}

To test it again, as below, we find that test 2 can be compiled by:

public class Testanimal {public static void main (string[] args) {Animaltrainer Animaltrainer = new Animaltrainer ();//test 1list<animal> animallist = new arraylist<> (), Animallist.add (New Cat ("CAT1")), Animallist.add (New Bird (" Bird1 ")); Animaltrainer.act (animallist);//Can be compiled//test 2list<cat> catlist = new arraylist<> (); Catlist.add (New Cat ("CAT2")), Catlist.add (New Cat ("CAT3")), Animaltrainer.act (catlist);//can also be compiled}}

After the above analysis, we can know that list<animal> and list<cat> are list< Extends animal> sub-type, similar to list<bird>,list<magpie> is also list< Extends subtype of animal>. As summarized below, for the upper bounds of the wildcard, there are the following basic rules: (assuming the given generic type is g, (such as list in list<e>), two specific generic parameters x, y, where y is the subclass of X (e.g. animal and cat above))

    • g<? Extends y> is g< Extends subtype of x> (e.g. list<?) Extends cat> is list< The subtype of the extends animal>).
    • G<x> is g< Extends X> sub-type (such as list<animal> is list<? Extends animal> sub-type)
    • G<?> and g<? Extends object> equivalent, such as list<?> and list< Extends objext> equivalent.

Learning here, you may encounter some doubts, or things can not understand the place, first observe the following two snippets of code, to determine whether it is feasible??

public void Testadd (list<? extends animal> List) {//.... Other logical List.add (new Animal ("Animal")), List.add (New Bird ("Bird")), List.add (New Cat ("Cat"));
list<? Extends animal> list = new arraylist<> () List.add (New Animal ("Animal")); List.add (New Bird ("Bird")); List.add ( New Cat ("Cat"));

The first analysis is as follows: because "? Extends Animal "can represent Animal or its subclasses (BIRD,CAT), the above operation should be feasible. In fact, " no ", that is, cannot be compiled. Why??

Before you explain, re-emphasize the rules you already know: Only animal class objects and their subclass objects (such as Cat and Bird objects) can be added to the list<aimal> list in list<bird> Can only add the bird class and its subclass objects (such as Magpie), you cannot add animal objects (not bird subclasses), similar to list<cat> and list<magpie> can only add cat and bird objects (or their subclass objects, but this is not listed). Now look back at the Testadd () method, we know that list<animal>, list<cat, etc. are list< Extends subtype of animal>. Assuming that the passed-in parameter is List<animal>, then the three "add" operations of the first code are feasible, but what if it is list<bird>? Only the second "add" can be executed, and assuming that the incoming list<tiger> (Tiger is imaginary and can be considered a subclass of cat), three "add" operations cannot be performed.

Now on the other hand, to give Testadd a different parameter, three "add" operation can raise the type incompatibility problem, and the parameters passed in is unknown, so Java in order to protect the type consistent, prohibit to list< Extends animal> add any object, but you can add null, that is, list.add (null) is possible. With the foundation mentioned above, it is not difficult to understand the second piece of code, because list< Extends type of animal> "? Extends Animal "cannot be determined, it can be animal,bird or cat, so to protect the consistency of its type, you cannot add any objects to the list, but you can add null.

First summed up as follows: Can not go to list< Extends animal> add any object, except NULL.

Another point of caution is that in list< Extends animal> can be Animal class object or Bird object (just some kind of object), conversely, in list< Extends Animal> list is Animal object, that is, bird is also Animal object, Cat is also Animal object (in the Java language, the subclass can point to the parent class, but the parent class cannot point to the child class), Then all the methods in the animal can be called, as follows:

for (Animal animal:list) {animal.eat ();}

Second, the lower bound of the wildcard character

Now that you have the upper bound of the wildcard, you naturally have the lower bound of the wildcard character. You can define the lower bound of the wildcard character list<? Super Bird>, where "Bird" is the lower bound of the wildcard character. NOTE: You cannot declare both the upper and lower bounds of a generic wildcard declaration at the same time.

Before we go into the details, let's look at the rules for using wildcards--for the upper bounds of wildcards, there are several basic rules: (assuming a given generic type is g, such as list in list<e>), two specific generic parameters x, Y, Where Y is the subclass of X (e.g. animal and cat above))

    • g<? Super x> is g<? Super Y> subtype (e.g. list<?) Super animal> is list<? Super Bird> subtype).
    • G<x> is g< The sub-type of super x> (e.g. list<animal> is list<? Super Animal> sub-type)

Now look at the following code to determine if it is logical:

public void Testadd (LIST<? Super Bird> List) {list.add (New Bird ("Bird")); List.add (New Magpie ("Magpie"));}
list<? Super Bird> list = new arraylist<> (), List.add (New Bird ("Bird")), List.add (New Magpie ("Magpie")), List.add (new Animal ("Animal"));

Look at the first piece of code, which is analyzed as follows, because "? Super Bird "represents Bird or its parent class, and Magpie is a subclass of Bird, so the appeal code cannot be compiled. And the fact is " line ", why? 2?

Before troubleshoot, to emphasize a point of knowledge, subclasses can point to the parent class, that is, bird is also the animal object. Now consider all possible arguments passed into Testadd (), which can be list<bird>,list<animal>, or list<objext>, and so on, to find that the type of these parameters is Bird or its parent class. Then we can see, the bird, magpie as bird objects, can also be bird, magpie as animal objects, similar can be seen as object objects, and finally found these added to the list< The objects in the Supe bird> list are all of the same class objects (test 1, as mentioned at the beginning of this article), so the Testadd method is logical and can be compiled. :

Now take a look at the second code for the second to third line of code is interpreted as above, as for the last line "List.add (New Animal (" Animal ")" is not compiled, why?? In order to protect the consistency of the type, because "? Super Bird "can be animal, or it can be an object or other Bird parent class, because cannot determine its type, also cannot go to list< Super Bird> Add any parent object of Bird.

Now that the parent object cannot be determined, how do I traverse the list<? Super bird>? Because object is the root class of all classes, you can use object to traverse it. But it seems to have little meaning.

for (Object object:list) {//...}

That "? Super Boundingtype "can be applied in what place?? “? Super Boundingtype "is a relatively wide application, but it is mixed. Here's a simple example. First assume that there are the following two student and Collegestudent, in which Collegestudent inherits student, as follows:

public class Student implements Comparable<student>{private int id;public Student (int id) {this.id = ID;} @Overridepublic int compareTo (Student o) {return (id > O.id)? 1: ((ID < o.id)? -1:0);}}
public class Collegestudent extends Student{public collegestudent (int id) {super (ID);}}


They need to be sorted based on their ID (note that this is a sort of array object), and the design method is as follows (the number of elements in the N exponential group):

public static <t extends Comparable<? Super t>> void Selectionsort (t[] a,int N)

First understand the meaning of this method, first <t extends comparable<t>> specifies that the object in the array must implement the comparable interface, COMPARABLE< Super t> indicates that if the parent implements the comparable interface, it itself is not implemented, such as collegestudent. First assume that there is an array of collegestudent, as follows:

collegestudent[] stu = new collegestudent[]{   new Collegestudent (3), New Collegestudent (2),   new Collegestudent ( 5), New Collegestudent (4)};


The execution method Selectionsort (stu,4) is fully accessible. If the Selectionsort method is defined as follows:

public static <t extends comparable<t>> void Selectionsort (t[] a,int N)

The method Selectionsort (stu,4) cannot be executed because Collegestudent does not implement the Comparable<collegestudent> interface. In other words, "? Super T "makes the Selectionsort method more generic. Selectionsort the implementation of the complete code can refer to the end of this article.

Three, unbounded wildcard characters

Know the upper and lower bounds of the wildcard, in fact, it is also equivalent to know the unbounded wildcard, without any modification can be, a single "? ”。 such as List<?>, "? "Can represent any type," arbitrary "is an unknown type. Unbounded wildcard characters are typically used in the following two scenarios:1, when the method is using the original object type as a parameter, as follows:

public static void Printlist (List<object> List) {for    (Object elem:list)        System.out.println (Elem + ""); 
   system.out.println ();}

You can choose to implement the following:

public static void Printlist (List<?> List) {for    (Object elem:list)        System.out.print (Elem + "");    System.out.println ();}

This can be compatible with more output, not simply List<object>, as follows:

List<integer> li = arrays.aslist (1, 2, 3); list<string>  ls = arrays.aslist ("One", "one", "three");p Rintlist (LI);p rintlist (LS);

2. The business logic of the method body defined is independent of the generic type , such as List.size,list.cleat. In fact, the most common is class<?>, because class<t> is not dependent on T.

The last reminder is that,list<object> and list<?> are not the same,list<object> as the list<?> subclasses. There is no way to add any objects to the list<?> list, except NULL.

Appendix: Selectionsort Code Implementation: (Best to rewrite Student's ToString method if you need to implement better output)

public class Sortarray {//For a set of array objects, the number of elements in the N exponential group is public static <t extends Comparable<? super t>> void Selecti Onsort (t[] a,int N) {for (int index = 0; index < n-1; index++) {int indexofsmallest = getindexofsmallest (a,index,n-1); s WAP (a,index,indexofsmallest);}} public static <t extends Comparable<?  Super t>> int getindexofsmallest (t[] A, int first, int last) {T minValue = A[first];//Assuming that a minvalueint indexofmin = First;  Get minValue subscript for (int index = first + 1, index <= last; index++) {if (A[index].compareto (MinValue) < 0) {MinValue = A[index];indexofmin = Index;}} return indexofmin;} public static void Swap (object[] A,int first,int second) {Object temp = A[first];a[first] = A[second];a[second] = temp;} public static void Main (string[] args) {collegestudent[] stu = new Collegestudent[]{new collegestudent (3), new Collegestud ENT (2), New Collegestudent (5), New Collegestudent (4)};selectionsort (Stu, 4); for (Student Student:stu) { SYSTEM.OUT.PRINTLN (student);}}}

[Java Foundation]java wildcard character

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.