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.
-
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.
We tested
new BAge[]{newBAgenewBAge()};PrintAges.print(temps);
Output:
100100
Perfect operation.
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?
- 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:
- 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 a
ArrayList<BSize>
- You can't insert a bsize element because the list might point to a
ArrayList<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.
- 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
- 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"
? extends B
Ensures readability and ? super B
ensures writing.
? extends B
And ? 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