Java generics Knowledge (two)--<? Extends t> and <? Super t>

Source: Internet
Author: User
Tags object object

<? Extends t> and <? Super T> is the concept of "wildcard character (wildcards)" and "Boundary (Bounds)" in Java generics

    • <? Extends t> refers to " upper bound wildcard character (Upper Bounds wildcards)"
    • <? Super t> refers to the " Nether wildcard (Lower Bounds wildcards)"

1. Why use wildcard characters and boundaries?

In the process of using generics, a very awkward situation often arises. For example, we have the Fruit class, and its derived class, the Apple class, in the case of the main topic.

class Fruit {} class extends Fruit {}

Then there is a simplest container: the plate class. You can put a generic "thing" on the plate. We can do the simplest "put" and "take" actions on this thing: the set () and get () methods.

 Public class Plate<t> {    private  T item;      Public Plate (T t) {        this. Item = t;    }       Public T GetItem () {        return  item;    }      Public void SetItem (T item) {        this. Item = item;    }} 

Now I define a " fruit plate ", logically the fruit plate can certainly pack apples.

plate<fruit> p=New plate<apple> (new Apple ());

But in fact the Java compiler does not allow this operation. Will error, "The Apple tray " cannot be converted into a "fruit plate ".

Type Mismatch:cannot convert from plate<apple> to plate<fruit>

So my embarrassment was made. In fact, the logic found in the compiler's head is this:

    • Apple is-a fruit
    • An apple plate not-is-a a plate of fruit.

So, even if there is an inheritance between the contents of the container, there is no inheritance between the containers. So we can not pass the plate<apple> reference to plate<fruit>.

To make the generics more comfortable, Sun's big brains came up with <. Extends t> and <? Super T> the way to get the "fruit plate" and "apple plate" between the sex.

2. What is an upper bound?

The following code is " upper bound wildcard character (Upper Bounds wildcards)":

extends Fruit>

Adult words are: a plate that can put fruit and everything is a fruit-derived class. the more straightforward point is: what fruit can be put on the plate. this is closer to the logic of our humanity. plate<? Extends Fruit> and plate<apple> the biggest difference is:plate< Extends fruit> is the base class for plate<fruit> and Plate<apple>. the direct benefit is that we can use the " Apple plate " To assign a " fruit plate ".

extends fruit> p=New plate<apple> (new Apple ());

If the fruit and Apple examples are expanded, the food is divided into fruits and meats, fruit with apples and bananas, meat with pork and beef, and apples to two green apples and red apples.

//Lev 1classfood{}//Lev 2classFruitextendsfood{}classMeatextendsfood{}//Lev 3classAppleextendsFruit {}classBananaextendsfruit{}classPorkextendsmeat{}classBeefextendsmeat{}//Lev 4classReadappleextendsapple{}classGreenappleextendsapple{}

In this system, the upper bound wildcard character "PLATE< Extends fruit> "covered in blue area

3. What is the nether?

corresponding,"Nether wildcard (Lower Bounds wildcards)":

Super Fruit>

The opposite concept is expressed: a plate that can put fruit and everything is a fruit-based class. plate<? Super Fruit> is the base class for plate<fruit>, but not the base class for plate<apple>. corresponding to the example just now, plate< Super Fruit> covers the areas of red.

4. Side-effects of upper and lower bounds wildcard characters

Boundaries make it easier to convert between different generics in Java. Do not forget, however, that such conversions also have some side effects. That is, some of the functionality of the container may fail.

Just take the plate as an example. We can do two things on the plate, set () something new on the plate, and get () something from the plate.

 Public class Plate<t> {    private  T item;      Public Plate (T t) {        this. Item = t;    }       Public T GetItem () {        return  item;    }      Public void SetItem (T item) {        this. Item = item;    }} 
4.1 Upper bound <? Extends t> can not be stored in, can only be taken out

< extends fruit> will invalidate the set () method that puts things on the plate. But fetching the thing get () method is also valid. For example, the following two set () methods, insert Apple and fruit both error.

 plate<? extends  fruit> fruitplate = new  plate<apple> (new   Apple ());  //  cannot deposit any element  Fruitplate.setitem (new  Apple ())    ; // error compilation error  Fruitplate.setitem (new  Fruit ()    ); // error compilation error  //  What you read can only be placed in fruit or its base class  Fruit newfruit1=fruitplate.getitem (); Object newFruit2  =  Fruitplate.getitem ();  Apple newFruit3  = Fruitplate.getitem (); // error  

The reason is that the compiler knows only that the container is fruit or its derived class, but specifically what type is not known. Could it be fruit? Could it be Apple? Or could it be banana,redapple,greenapple? After seeing the plate<apple> assignment, the compiler was not labeled "Apple" on the plate. Instead, it is marked with a placeholder:cap#1, which represents a subclass of fruit or fruit that is captured, specifically what class does not know, codenamed Cap#1. Then either you want to insert Apple or meat or the fruit compiler does not know if you can match this cap#1, so it is not allowed.

So the difference between the wildcard <?> and the type parameter <T> is that all T represents the same type for the compiler. For example, in the following generic method, three t all refer to the same type, either a string or an integer.

 public <T> list<t> Fill (t ... t);

But wildcard <?> no such constraint,plate<?> simply means: There 's a thing on the plate, what I don't know.

4.2 Nether <? Super t> does not affect the deposit, but it can only be placed in object.

use the Nether < the super fruit> will invalidate the Get () method that takes something from the plate and can only be stored in object. The set () method is normal.

 plate<? super  fruit> fruitplate = new  plate<fruit> (new   Fruit ());  //  deposit element normal  Fruitplate.setitem (new   Apple ()); Fruitplate.setitem ( new   Fruit ());  //  What you read can only be stored in the object class  Object newFruit1 = Fruitplate.getitem ();  Fruit newFruit2  = Fruitplate.getitem (); // error   Apple newFruit3 = Fruitplate.getitem (); // error  

Because the nether specifies the lower bound of the element's minimum granularity, it actually relaxes the type control of the container element. Since the element is the base class of fruit, it is possible to have a smaller particle size than the fruit. However, it is laborious to read the elements outward, only the base class object object of all classes can be loaded. But in this case, the type information of the element is all lost.

5. Pecs principle

Finally look at what is the PECS (Producer Extends Consumer Super) principle , which has been well understood:

    • When the content is read out frequently, it is suitable for upper bound extends.
    • Often inserted in, suitable for use in the Nether super.

Java generics Knowledge (two)--<? Extends t> and <? Super t>

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.