Use of Java generics

JDK1.5. Add a Generic type, that is, the type parameter Generic

The so-called genericity is to allow an identifier to represent the type of an attribute in a class or the return value and parameter type of a method when defining a class or interface
This type parameter will be determined when used (declaring variables, creating objects, and calling methods (generic methods) with this type) (i.e., passing in actual type parameters, also known as type arguments)

Why generics

Isn't it possible to store data directly with Object

1. Solve the security problem of element storage, such as commodity and drug labels, without making mistakes

2. Solve the problem of type cast when obtaining data elements

Generic advantages

It can detect errors at compile time rather than at run time to increase readability and stability

Naming conventions single character uppercase, e.g. E T K V

Use of generics

Generic class, generic interface; generic method

  1. T can only be "class" and cannot be filled with basic data type, but can be filled with wrapper class
  2. The constructor of the generic class is as follows: public GenericClass() {}
  3. Different generic references cannot be assigned to each other. Although ArrayList and ArrayList are two types at compile time, only one ArrayList is loaded into the JVM at run time
    ArrayList list1 = null, ArrayList List2 = list1; // FALSE
  4. If a generic type is not specified, the type corresponding to the generic type is treated as Object, but it is not equivalent to Object
    Experience: generics can be used all the way or not all the way
// Do not use generics
public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("a");
        list.add(new Date());// Strong conversion to ClassCastException
        test(list);// Generic erasure, compilation does not check
    }
    public static void test(ArrayList<String> list) {
        for (String s : list) {
            System.out.println(s);
        }
    }
 // <Object>
 public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>();
        list.add("a");
        list.add(new Date());
        test(list);// Once the Object class is specified, the compilation will type check. There is an error in compilation here
    }
    public static void test(ArrayList<String> list) {
        for (String s : list) {
            System.out.println(s);
        }
    }

Static methods use generics

public class Order<E> {
    String orderName;
    int orderId;
    E orderE;
    public Order() { 
        // Cannot directly new E []
        E[] a = (E[])new Object[10];
    }
    public Order(String orderName, int orderId, E orderE) {
        this.orderName = orderName;
        this.orderId = orderId;
        this.orderE = orderE;
    }
    // Generic methods can be static. Generic parameters are determined when calling methods, not when instantiating classes,  
    public static <T> List<T> copy(T[] arr){ 
        ArrayList<T> list = new ArrayList<>();
        for(T t : arr)
            list.add(t);
        return list;
    }
    // Class generics cannot be used in static methods. Static structure loading is earlier than object creation
    /*public static void show(E orderE){ // Compilation error
        System.out.println(orderE);
    }*/
}

Exception cannot be generic

public class MyException extends Exception {} / / error

try{
} catch(T t){
}Compilation failed

Generic class

public class B extends A<String> {
    public static void main(String[] args) {
        B b = new B();
        b.setName("a");
        String name = b.getName();
        System.out.println(name); // a
        A<Integer> a = new A<>();
        a.setName(1);
        Integer name1 = a.getName();
        System.out.println(name1);// 1
    }
}
public class A<E> {
    private E name;
    private int age;
    get method
    set method
}

class Father<T1, T2> {
}

class Son1<A,B> extends Father { 
    // The data type of the parent class is Object
}

class Son2<A,B> extends Father<Integer, String> { 
    // The data type of the parent class is Integer, String
}

class Son3<T1, T2, A, B> extends Father<T1, T2> {
    // What types are the subclasses T1 and T2? What types are the parent classes T1 and T2
}

class Son4<T2, A, B>  extends Father<Integer, T2> {
	// What type is the child class T2? What type is the parent class T2
}

Usage scenarios for generic classes

Universal CRUD

public class DAO<T>{
	// Add, delete, modify and query
    public void add(T t){
        ...
    }
    ...
}
public class Customer {
    private String name;
}
public class CustomerDAO extends DAO<Customer> {
    // DAO is a general method of operating database
}
public class EmpDAO extends DAO<Emp> {
}

public class Test{
  	public static void main(String[] args) {
        CustomerDAO dao = new CustomerDAO();
        dao.add(new Customer("tom"));
	}
}

generic interface

Similar to generic classes
...

generic method

Method return value preceded by < T >, or static < T >

public class Test{
    public static void main(String[] args) {
		Test test = new Test();
		Integer[] arr = new Integer[]{1, 2, 3};
         List<Integer> list = test.copyFromArrayToList(arr);
		}
    // This method is generic
    // When the method is called, E is determined 
    public <E> List<E> copyFromArrayToList(E[] arr) {
    	ArrayList<E> lsit = new ArrayList<>();
    	for(E e : arr) {
        	list.add(e);
			}
    	return list;
		}
}

Attention

Embodiment in inheritance

Object obj = null; 
String str = null; 
obj = str;
Object[] arr1 = null; 
String[] arr2 = null;
arr1 = arr2; 

List<Object> list1 = null;
List<String> lsit2 = null;
// list1 and list2 have no child parent relationship at this time 
// list1 = list2;  error
// Class A is the parent of class B, but g < a > and G < b > have no child parent relationship
// Class A is the parent of class B, but a < g > has a child parent relationship with B < g >

Collection< Object >,Collection,Collection< String>

/*	Compare the three differences:
printCollection(Collection c)
printCollection(Collection<Object> c)
printCollection(Collection<String> c)
*/
public class T {
    public static void main(String[] args) {
        // I:
        List list = new ArrayList();//You can call methods 1 and 2, and calling 3 will force an error
        list.add("A");
        list.add(1);
        printCollection(list);
        // II:
      	List<String> list = new ArrayList<>(); //You can call 1,3 to call 2. Compilation error
        list.add("A");
        list.add("Aa");
        printCollection(list);
    }
    
    // 1
//    public static void printCollection(Collection c) {
//        Iterator i = c.iterator();
//        for (int k = 0; k < c.size(); k++) {
//            System.out.println(i.next());
//        }
//    }
    // 2
    public static void printCollection(Collection<Object> c) {
        for (Object e : c) {
            System.out.println(e);
        }
    }
    // 3
//   public static void printCollection(Collection<String> c) {
//        for (String e : c) {
//            System.out.println(e);
//        }
//    }
    Note: 1, 2, 3 Cannot exist at the same time, compilation will make an error
}

wildcard

Wildcard use? express

be careful

Cannot be used on generic method declarations. Public static <? > void test(ArrayList list){ }
Cannot be used on declaration of generic class class generictypeclass <? > { }
Cannot be used to create an object ArrayList <? > list2 = new ArrayList <?> ();

unlimited

 // It is similar to equals (Object obj)
    public void print(List<?> list){
        Iterator<?> iterator = list.iterator();
        while(iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }
    // If there is no wildcard, write many traversal methods
    public void print1(List<String> list){
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
    public void print2(List<Integer> list){
        Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

upper bound

<? extends Person>

public static void printCollection3(Collection<? extends Person> coll) {
    Iterator<?> iterator = coll.iterator();
    while (iterator.hasNext()) {
    	System.out.println(iterator.next());
    }
}  // Because it can only be Person or a subclass of Person

Lower bound

<? super Person>

public static void printCollection4(Collection<? super Person> coll) {

    Iterator<?> iterator = coll.iterator();
    while (iterator.hasNext()) {
   		System.out.println(iterator.next());
    }
} // Because it can only be Person or the parent class of Person 

Keywords: Java

Added by bpgillett on Sun, 02 Jan 2022 04:31:58 +0200