java Generics T and ? difference

 1) first we must know this fact: the actual type of an variable is uncertain. a parent class declared variable can actually be a child class type. a parent can represent a child, a child can not represent a parent, it only represent itself or the child of itself.

```java:Test.java
package test;

import java.util.ArrayList;
import java.util.List;

public class Test<T> {

	public static void main(String[] args) {
		Object obj;
		Number num;
		Integer in = 10;
		System.out.println("in is " + in.getClass().getCanonicalName());

		num = in;
		System.out.println("num is " + num.getClass().getCanonicalName());
		// java.lang.Integer

		obj = in;
		System.out.println("obj is " + obj.getClass().getCanonicalName());
		// java.lang.Integer

		List<Object> objList = new ArrayList<Object>();
		List<Number> numList = new ArrayList<Number>();
		List<Integer> inList = new ArrayList<Integer>();

		inList.add(in);
		System.out.println("inList is " + inList.getClass().getCanonicalName());
		System.out.println("inList.get(0) is " + inList.get(0).getClass().getCanonicalName());

		numList.add(in);
		System.out.println("numList is " + numList.getClass().getCanonicalName());
		System.out.println("numList.get(0) is " + numList.get(0).getClass().getCanonicalName());

		objList.add(in);
		System.out.println("objList is " + objList.getClass().getCanonicalName());
		System.out.println("objList.get(0) is " + objList.get(0).getClass().getCanonicalName());
	}
}

```
```
in is java.lang.Integer
num is java.lang.Integer
obj is java.lang.Integer
inList is java.util.ArrayList
inList.get(0) is java.lang.Integer
numList is java.util.ArrayList
numList.get(0) is java.lang.Integer
objList is java.util.ArrayList
objList.get(0) is java.lang.Integer
```
2)  should we let a `List<Object>` declared variable represent a  `List<Integer>` type ? The answer is NO. let us think about this. 

```java:
		List<Object> objList1 = new ArrayList<Object>();
		List<Object> objList2 = new ArrayList<Number>();//if it can be true here then next step will be error.
		objList2.add(new Object);//error! objList2 actually is a List< Number > !
```
3) so we have no choice! let `List<Object> = new List<Object>` is the only way to keep safe.

4) but we really want a syntax to let `List<Parent>` variable represent `List<Child>`, because there are too many children type. child1, child2, child3, .... we want a syntax to let variable represent one of `List< child1>` , `List<child2>`, `List<child3>`, ...  be careful. we know that `List<child1>` and  `List<child2>` can not represent each other. but we want to declare that `List<? extends Parent>` can represent `List<child1>` when it is `= new List<child1>()`. or it can represent `List<child2>` when it is `= new List<child2>()`. etc.  when we see `List<? extends Parent> g` ,we know that g actually is a `List<child1>` or a `List<child2>` or a `List<child3>`  or `List< Parent >`. **one of them , not any of them!** so we use the `? extends Parent ` instead of `* extends Parent`.

5) because `List<? extends Parent> g ` actually is `List<ChildX>` , we can read from  `List<ChildX>` use a `Parent` type variable. we can not put a `Parent` or a `Child` to its element position. because actually the element position may be `Child1` type. maybe  `Child2` type... anyway, it is uncertain. what we know is it must look like a Parent type. we can read from the element position then use it as a Parent. but we can not replace it. if we do so ,we may break the rule to make ` Child <= Parent ` happens! or `Child1 <= Child2`. that must be forbidden!  

6) then let us see `List<? super Parent> g ` . it represent a `List<P1>`, or `List<P2>`, or `List<P3>`, ... which P1 is parent of Parent, P2 is parent of Parent, P3 is parent of Parent... 

7) we can safely set a child of Parent to the g's element just like ` Parent p = new Child()`. also we face the uncertainty. so we can not actually read from the element unless we use `Object p = g.get(0)`.

8) when to use ? let us think about this scenario: we want a `List<T> => List<T,T> convert`

```java:DoubleElement.java
package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DoubleElement<T> {
	public final T x;
	public final T y;

	public DoubleElement(T e) {
		this.x = e;
		this.y = e;
	}
	
	
	@Override
	public String toString() {
		return "{x:" + x + ", y:" + y + "}";
	}

	public static <T> List<DoubleElement<T>> toDoubleElementArray(List<T> list) {
		List<DoubleElement<T>> doubleElementArray = new ArrayList<DoubleElement<T>>(list.size());
		for (T e : list) {
			doubleElementArray.add(new DoubleElement<T>(e));
		}
		return doubleElementArray;
	}

	public static void main(String[] args) {
		List<Integer> inList = Arrays.asList(new Integer[] { 1, 2, 3 });
		List<Number> numList = Arrays.asList(new Number[] { 1, 2.5f, 3 });
		List<Float> floatList = Arrays.asList(new Float[] { 1.1f, 2.2f, 3.3f });

		List<DoubleElement<Integer>> doubleInList = DoubleElement.toDoubleElementArray(inList);
		System.out.println(doubleInList);
		List<DoubleElement<Number>> doubleNumList = DoubleElement.toDoubleElementArray(numList);
		System.out.println(doubleNumList);
		List<DoubleElement<Float>> doubleFloatList = DoubleElement.toDoubleElementArray(floatList);
		System.out.println(doubleFloatList);

		//we want to constraint this because we only want to use Number and its Child to work.
		List<String> strList = Arrays.asList(new String[] { " I ", " am ", " evil !" });
		List<Object> objList = Arrays.asList(new Object[] { " I ", " am ", " evil !", " too !" });

		List<DoubleElement<String>> doubleStrList = DoubleElement.toDoubleElementArray(strList);
		System.out.println(doubleStrList);

		List<DoubleElement<Object>> doubleObjList = DoubleElement.toDoubleElementArray(objList);
		System.out.println(doubleObjList);
	}
}
```
```
[{x:1, y:1}, {x:2, y:2}, {x:3, y:3}]
[{x:1, y:1}, {x:2.5, y:2.5}, {x:3, y:3}]
[{x:1.1, y:1.1}, {x:2.2, y:2.2}, {x:3.3, y:3.3}]
[{x: I , y: I }, {x: am , y: am }, {x: evil !, y: evil !}]
[{x: I , y: I }, {x: am , y: am }, {x: evil !, y: evil !}, {x: too !, y: too !}]
```


T works fine. but we want to add a constraint to T. only `List<Number>` and its Child `List<Float>` `List<Integer>` ... can use this method. how to ?  

```java
public static <T> List<DoubleElement<Number>> toDoubleElementArray(List<Number> list) {
//this will well done with List<Number> but not List<Float> or List<Integer> or ...
```
yes! it is showtime of  `List<? extends Number>`  !

```java:DoubleElement.java
package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DoubleElement<T> {
	public final T x;
	public final T y;

	public DoubleElement(T e) {
		this.x = e;
		this.y = e;
	}

	@Override
	public String toString() {
		return "{x:" + x + ", y:" + y + "}";
	}

	public static List<DoubleElement<? extends Number>> toDoubleElementArray(List<? extends Number> list) {
		List<DoubleElement<? extends Number>> doubleElementArray = new ArrayList<DoubleElement<? extends Number>>(
				list.size());
		for (Number e : list) {
			doubleElementArray.add(new DoubleElement<Number>(e));
		}

		return doubleElementArray;
	}

	public static void main(String[] args) {
		List<Integer> inList = Arrays.asList(new Integer[] { 1, 2, 3 });
		List<Number> numList = Arrays.asList(new Number[] { 1, 2.5f, 3 });
		List<Float> floatList = Arrays.asList(new Float[] { 1.1f, 2.2f, 3.3f });

		List<DoubleElement<? extends Number>> doubleInList = DoubleElement.toDoubleElementArray(inList);
		System.out.println(doubleInList);
		List<DoubleElement<? extends Number>> doubleNumList = DoubleElement.toDoubleElementArray(numList);
		System.out.println(doubleNumList);
		List<DoubleElement<? extends Number>> doubleFloatList = DoubleElement.toDoubleElementArray(floatList);
		System.out.println(doubleFloatList);
		
        //we want to constraint this because we only want to use Number and its Child to work.
        List<String> strList = Arrays.asList(new String[] { " I ", " am ", " evil !" });
        List<Object> objList = Arrays.asList(new Object[] { " I ", " am ", " evil !", " too !" });
        
        //this will compile error!
        List<DoubleElement<String>> doubleStrList = DoubleElement.toDoubleElementArray(strList);
        System.out.println(doubleStrList);
        //this will compile error!
        List<DoubleElement<Object>> doubleObjList = DoubleElement.toDoubleElementArray(objList);
        System.out.println(doubleObjList);

	}
}
```
9) at last. let us see an example of <? super T>

```java
/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.

 */
package java.util.function;

import java.util.Objects;

/**
 * Represents a function that accepts one argument and produces a result.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #apply(Object)}.
 *
 * @param <T> the type of the input to the function
 * @param <R> the type of the result of the function
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);

    /**
     * Returns a composed function that first applies the {@code before}
     * function to its input, and then applies this function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of input to the {@code before} function, and to the
     *           composed function
     * @param before the function to apply before this function is applied
     * @return a composed function that first applies the {@code before}
     * function and then applies this function
     * @throws NullPointerException if before is null
     *
     * @see #andThen(Function)
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    /**
     * Returns a composed function that first applies this function to
     * its input, and then applies the {@code after} function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of output of the {@code after} function, and of the
     *           composed function
     * @param after the function to apply after this function is applied
     * @return a composed function that first applies this function and then
     * applies the {@code after} function
     * @throws NullPointerException if after is null
     *
     * @see #compose(Function)
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    /**
     * Returns a function that always returns its input argument.
     *
     * @param <T> the type of the input and output objects to the function
     * @return a function that always returns its input argument
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}
```
```TestFunction.java
package test;

import java.util.function.Function;

public class TestFunction {

	public static void main(String[] args) {

		Function<Integer, Float> func = e -> {
			return e + 5.5f;
		};
		
		Function<Number, Number> func2 = e -> {
			return Math.round(e.floatValue());
		};
		
		//OK round( e+5.5 )
		Number result = func.andThen(func2).apply(5);
		System.out.println(result);
	   
		//this will constraint you because the <? super Float>
		Function<Integer, Number> func3 = e -> {
			return Math.round(e.floatValue());
		};
		
		//compile error!
		Number result3 = func.andThen(func3).apply(5);
		System.out.println(result);
	}
}
```
10) that's all. let us have a good weekend!