T and java generics wildcards?

The basic usage of a generic

Java5 from the start, java began to introduce generics. In the absence of generics, to read from the collection of each object must be converted, if someone accidentally inserted the wrong type of object, the conversion process in the run-time error occurs.
Here Insert Picture DescriptionHere Insert Picture Description
Once you have generics, you can tell the compiler which object type for each set of acceptance. The compiler automatically converts your insertion, whether inserted inform the wrong type of object pancake ah compile time.

definition

· 1 defined in the class, followed by the class name

  public class TestClassDefine<T, S extends T>{}

Define a generic T, S, T and S inheritance

· 2 defined behind the character decoration method, immediately behind the modifier (public)

  public <T, S extends T> T testGenericMethodDefine(T t, S s){}

Define a generic T, S, T and S inheritance

Operating principle

java generics is run by wiping, that will not take effect during the operation of the code, compile only take effect.

List<String> stringArrayList = new ArrayList<String>();
List<Integer> integerArrayList = new ArrayList<Integer>();

Class classStringArrayList = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();

if(classStringArrayList.equals(classIntegerArrayList)){
    Log.d("泛型测试","类型相同");
}

Output Results: D / generic test: same type.
This sentence summarized: the generic type to logically as a plurality of different types, are actually the same basic type.

Two? PECS law

Parameterized type is unchanged.
For any two distinct types? Type1 and Type2 terms, List <Type1> is neither a List <Type2> subtype, nor is it a super-type. That while the String? Subtype of Object class, but List <String> has never been? List <Object> subtype

We define a class Stack:

public  class Stack<E> {
    public Stack();
    public void push(E e);
    public E pop();
    public boolean isEmpty();
}

If we try to define a pushAll method, in order to make it into a series of elements in the stack

    public void pushAll(Iterable<E> src) {
        for (E e : src) {
            push(e);
        }
    }

In compile this method is correct, consider the definition of a? Stack <Number>, and call pushAll, parameter passing is? Integer type, according to the logic that this is possible because Integer is a subclass of Number.

 Stack<Number> numberStack = new Stack<>();
        Iterable<Integer> integerIterable = new ArrayList<Integer>();
        numberStack.pushAll(integerIterable);

But this can not be compiled by
Here Insert Picture Description
this time we wildcard? It comes in handy

    public void pushAll(Iterable<? extends E> src) {
        for (E e : src) {
            push(e);
        }
    }

Input Parameter Type pushAll should not be? Iterable interface to E, but should be a subtype of Iterable E interface. Wildcard type Iterable <? Extends E> formal mean.

Here Insert Picture Description
Calls can already be normal.

Now suppose you want to write a popAll methods and pushAll correspondence. That the element is ejected from the stack, and collected in the collection specified:

    public void popAll(Collection<E> dst) {
        while (!isEmpty()) {
            dst.add(pop());
        }
    }

Similarly, if a stack element type and the target set an exact match, then compile and run well.
Now suppose you have a Stack <Number> and object types of variables, Pops an element from the stack stored in the object, press the error should say
Here Insert Picture Description
can see or get an error similar to the first time pushAll: Collection <Number> not Collection <Object> subtype.
We can be modified as follows:

    public void popAll(Collection<? super E> dst) {
        while (!isEmpty()) {
            dst.add(pop());
        }
    }

Then we would not have the above code the error. Input Parameter Type popAll E should not be set, but rather is a collection of some kind of extra class E.

The conclusion is clear: in order to obtain maximum flexibility to use wildcards to represent the type of the input parameters of the producer or the consumer.

PECS represents producer-extends, consumer-super
if parameterized type represents a producer T, on the use? <Extends T?>;? If he said a consumer T, on the use of <super T?>.

And remember: the Comparable and Comparator is a consumer

And three T? More scenes

1. Note that we can not add any elements to the List <?>, In addition to null, even with the upper and lower boundaries too.
2, try not to use wildcard characters in the return value, as this will force users to use wildcards in the client code, if the user must consider the wildcard type, greatly increase the possibility of error api
3, is always Comparable <? Super T> takes precedence over Comparable <T>, is always Comparator <? super T> takes precedence over the Comparator <T>
4, there is a problem worthy of discussion

    public static <E> void swap(List<E> list, int i, int j);
    public static  void swap(List<?> list, int i, int j);

In javaAPI, the second is better, because it does not need to consider the type of parameters, but can freely pass the type of value list.
In general, if the type parameters appear only once in the process of life, you can replace it with a wildcard.

Released six original articles · won praise 10 · views 2715

Guess you like

Origin blog.csdn.net/weixin_40292704/article/details/103988501
Recommended