Generic wildcard characters in Java Java--from "sneaking" to changing the elements of a collection

Source: Internet
Author: User

Have not paid attention to this aspect of the content, think this is the basis, wrote this note.

First of all, there are three Java wildcard characters ———— don't be nervous, now it's just a rough look, don't really matter

type Introduction
<?> Unqualified wildcard character, equivalent to < Extends object>
<? Extends number> A maximum wildcard character that indicates that the parameter type can only be a subclass of number or number.
<? Super number> The lower bound wildcard character, which indicates that the parameter type can only be the parent of number or number.

Then let's define four classes, and we'll use the following

classA PublicStringGetName() {return "A"; }}classBextendsa{@Override     PublicStringGetName() {return "B"; }}classBageextendsb{@Override     PublicStringGetName() {return "C"; } Public int Getage() {return  -; }}classBsizeextendsb{@Override     PublicStringGetName() {return "D"; } Public int GetSize() {return-1; }}
From a strange phenomenon.
  1. First, we introduce a class printages to print Bage getage ()

    < span class= "kw" >class  printages{public  static  void  print  (bage[] Ages)    {if  (ages = = null ) return ; for  (Bage bage:ages) {if  (bage! = null ) System. out . println  (Bage. getage     ()); }}}  

    Take a closer look at this class above, what do you think of the printages I wrote? Is it perfect enough to not throw an exception? I think it's perfect, and I'm sure there won't be any anomalies in my code.

  2. We tested

    new BAge[]{newBAgenewBAge()};PrintAges.print(temps);

Output:

100100

Perfect operation.

    1. We'll add two more lines.

      new BAge[]{newBAgenewBAge()};B[] barray = temps;  // 新增加的第一行barray[0newBSize// 新增加的第二行PrintAges.print(temps);

      You know what? I secretly changed the elements in the array! I assign an Bsize object to an element in an array of type Bage!
      Moreover, the compilation passed. But there must be an anomaly, which line do you think it is?

Output:

Exception in thread "main" java.lang.ArrayStoreException: JavaApp.BSize at JavaApp.JavaApplicationStudyGen.main(JavaApplicationStudyGen.java:33)

I thought I was going to have an exception in the Printages print method, but actually the newly added second line has a run-time error and an assignment error.

而在C#中,这种问题出现的可能性就更小了。C#中,新增的第一行是无法通过编译的。

So, this problem is in the collection ... Would it be accurate to say that it will appear in generics?

    1. The above issues are discussed in generics.

Let's first PrintAges add an overload of the print function

classprintages{ Public Static void Print(arraylist<bage> list) {if(List = =NULL)return; for(Bage age:list) System. out.println(age.Getage()); } Public Static void Print(bage[] Ages) {if(Ages = =NULL)return; for(Bage bage:ages) {if(Bage! =NULL) System. out.println(Bage.Getage()); }     }}

Then we'll run the following code again:

new ArrayList<BAge>();list.add(newBAge// 编译错误yourList.set(0newBSize// star 1BAge age = list.get(0// star 2PrintAges.print(list);

This time, Java processing is more rigorous, ArrayList<BAge> ArrayList<B> resulting in a compilation error when assigning to an object of type.

在 C# 里,也是一样的,在把 ArrayList<BAge> 赋值给 ArrayList<B> 类型的对象时会产生编译错误。

At first, I don't understand. The object referenced by the list ArrayList

However, the reason for not assigning a value is to put an object of the bsize type in a actually ArrayList

After the type erase, star 2 the code of the line becomes

BAge age = (BSize)list.get(0// star 2

This is completely wrong.

That is, we should prohibit ArrayList<B> yourList = new ArrayList<BAge>() assignments like this, otherwise there will be errors and surprises.

To be honest, B[] barray = new BAge[]{new BAge(), new BAge()} such assignment operations should also be banned, but Java can. see that C # is not allowed to do this (laughs)

Remember such a mistake. Next, we can talk about generic wildcard characters for Java.

Why wildcard characters are present

So the wildcard appears to provide a bit of convenience to the programmer at the same time that the error is avoided.

And how does a wildcard function? is a function of the three "rules of the game" given by the compiler (which is the rule in the table above).

It takes a little bit of logical power to understand at first:

    1. The upper bound wildcard <? extends B> ensures readability and <? extends B> 表示参数类型只能是 B 或是 B 的子类 can be compiled through the statement:
extendsnew// 编译错误extendsnew// okextendsnew// okextendsnew// ok

Based on the above compilation rules, we can draw the following facts:

    • You must be able to read a B element from the list because the list is either pointing ArrayList<B> to or pointing to the object containing the B-subclass.ArrayList<B>
    • You cannot insert a B element because the list might point to ArrayList<BSize> or point toArrayList<BAge>
    • You can't insert a bage element because the list might point to aArrayList<BSize>
    • You can't insert a bsize element because the list might point to aArrayList<BAge>

Note that in the above code, the list T is replaced by the? extends B

In other words, the read operation can be ensured that you can read from the list to a B element so that the list.get method can be used normally.

and is list.set(int, T) replaced list.set(int, ? extends B) , this method is "forbidden" by the compiler. In other words, if you write list.set(0, new B()) or you list.set(0, new BSize()) can't.

Here you have to ask questions, you do not say that the "rules of the game" <? extends B> 表示参数类型只能是 B 或是 B 的子类 on the line? I can only say that the text can convey a limited amount of information, this expression is only applicable to ArrayList<? extends B> list = new ArrayList<A>(); such an assignment moment. It depends on the "facts" derived above.

    1. The lower bound wildcard character <? super B> ensures a write
      "' Java
      arraylist<? Super B> list = new ArrayList

```

Based on the above compilation rules, we can draw the following facts:

    • You must be able to insert an object of type B or an object of type B. Because the list either points to a type B, or to a ArrayList ArrayList object that contains a B-type, such as the list might be ArrayList<Object> or ArrayList<A> .
    • You must not guarantee to read to B, because list may point to ArrayList<Object> or isArrayList<B>

This way, the list.set method can be used normally. Assuming list point ArrayList<Object> , we add an object of type B to the ArrayList<Object> right.

    • Or, we BAge can add an object to the ArrayList<Object> or, ArrayList<A> yes.
    • Or, we BSize can add an object to the ArrayList<Object> or, ArrayList<A> yes.
Summarize
    1. Wildcards appear to allow programmers to relax a little bit in case of the above error, so-called "rules that meet my compiler, make you comfortable"
    2. ? extends BEnsures readability and ? super B ensures writing.
    3. ? extends BAnd ? super B the feeling of giving the person is counter operation.

Generic wildcard characters in Java Java--from "sneaking" to changing the elements of a collection

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.