What is generics?
A generic type is a parameterized type. When a parameter is defined, there is a formal parameter, and then a parameter is passed when the method is called. Then, the type is parameterized from the original specific type, which is similar to the variable parameter in the method. The type is also defined in the form of parameter (called type parameter), and then the specific type (type parameter) is passed in during use
public class TestFanxing{ @Test public void TestFanxing(){ List<String> list = new ArrayList<String>(); list.add("qqyumidi"); list.add("corn"); //list.add(100); // 1 prompt compilation error for (int i = 0; i < list.size(); i++) { String name = list.get(i); // 2 System.out.println("name:" + name); } } }
After using generics, an error will be reported when adding an Integer type of Integer, because in the process of new, generics has determined the parameter type of generics, also known as the type that defines list < String >, so there is no need to cast at / / 2, because at this time, the collection can remember the type information of elements, and the compiler can confirm that it is a String type.
Combined with the above generic definition, we know that in the List, String is a type argument, that is, the corresponding List interface must contain type parameters. And the return result of the get() method is directly this parameter type (that is, the corresponding type argument). Let's take a look at the specific definition of the List interface:
public interface List<E> extends Collection<E> { int size(); boolean isEmpty(); boolean contains(Object o); Iterator<E> iterator(); Object[] toArray(); <T> T[] toArray(T[] a); boolean add(E e); boolean remove(Object o); boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean addAll(int index, Collection<? extends E> c); boolean removeAll(Collection<?> c); boolean retainAll(Collection<?> c); void clear(); boolean equals(Object o); int hashCode(); E get(int index); E set(int index, E element); void add(int index, E element); E remove(int index); int indexOf(Object o); int lastIndexOf(Object o); ListIterator<E> listIterator(); ListIterator<E> listIterator(int index); List<E> subList(int fromIndex, int toIndex);
As can be seen from the above code, after the generic definition is adopted in the List interface, E in represents type parameters and can accept specific type arguments. In this interface definition, wherever e appears, it represents the same type arguments accepted from the outside.
Type wildcard
|<? Super T >: indicates "yes"? The question mark is a subtype of T and cannot be other types that do not inherit this T type. Otherwise, an error will be reported. A reference type that can be logically used to represent both Box and Box's parent class is required. Therefore, the type wildcard is applied. Type wildcards are generally used? Instead of a specific type argument, it is not a type parameter, and Box < 2 > is logically the parent class of all Box < specific type arguments >, such as Box, Box... And so on. Thus, we can still define generic methods to meet such requirements|
@Test public void TestFanxing(){ List<String> list = new ArrayList<String>(); list.add("qqyumidi"); list.add("corn"); //list.add(100); // 1 prompt compilation error for (int i = 0; i < list.size(); i++) { String name = list.get(i); // 2 System.out.println("name:" + name); } Collection<String> cl = new ArrayList<>(); cl.addAll(list); cl.stream().forEach(System.out::println); }
Collection<? Extensions E > explanation:
1. The Collection interface is implemented
2. The type must be a subclass of E
Symbol interpretation:
?: wildcard
<? Super T > lower limit general distribution
Represents an unknown class, while t is a concrete class. In actual use, t needs to be replaced with a concrete class, indicating that the generic parameter is the parent class of T when instantiating.
public static void addNumbers(List<? super Integer> list) { for (int i = 1; i <= 10; i++) { list.add(i); } }
This means that when we call this method, the parameter we can pass in is Integer or the parent class of Integer, for example:
public class TestLowerBounded { public static void addNumbers(List<? super Integer> list) { for (int i = 1; i <= 10; i++) { list.add(i); } } public static void main(String[] args) { List<Integer> list1 = new ArrayList<>(); addNumbers(list1); List<Number> list2 = new ArrayList<>(); addNumbers(list2); List<Object> list3 = new ArrayList<>(); addNumbers(list3); List<String> list4 = new ArrayList<>(); //Compilation error because String is not a parent of Integer //addNumbers(list4); } }
Number and Object are both the parent classes of Integer, so they pass the compilation, while String is not the parent class of Integer, and an error is reported during compilation.