[JavaSE] Chapter 11 generics

11.1 role of generics

11.1.1 concept of generics

  • 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 (for example, inheriting or implementing this interface, declaring variables and creating objects with this type) (that is, passing in the actual type parameter, also known as the type argument)

  • Since JDK5, Java has introduced the concept of "Parameterized type", which allows us to specify the type of collection elements when creating a collection, such as: List < string >, which indicates that the list can only save objects of string type

11.1.2 role of generics

Java generics can ensure that ClassCastException exceptions will not be generated at runtime if the program does not issue a warning at compile time. At the same time, the code is more concise and robust

11.2 use of generics

11.2.1 using generics in Collections

  • The collection interface or collection class is modified to a generic structure in JDK5.
  • When instantiating a collection class, you can specify a specific generic type
  • After specifying, when defining a class or interface in a collection class or interface, the location where the generic type of the class is used by the internal structure is specified as the instantiated generic type
  • The type of a generic type must be a class, not a basic data type. The wrapper class is used for the location of the basic data type to be used
  • If the generic type is not specified when instantiating. The default type is Java lang.Object
ArrayList<Integer> list = new ArrayList<>();//Type inference
list.add(78);
list.add(88);
list.add(77);
list.add(66);
//Traversal mode 1:
//for(Integer i : list){
//No forced rotation is required
//System.out.println(i);
//}
//Traversal mode 2:
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
Map<String,Integer> map = new HashMap<String,Integer>();
map.put("Tom1",34);
map.put("Tom2",44);
map.put("Tom3",33);
map.put("Tom4",32);
//Add failed
//map.put(33, "Tom");
Set<Entry<String,Integer>> entrySet = map.entrySet();
Iterator<Entry<String,Integer>> iterator = entrySet.iterator();
while(iterator.hasNext()){
    Entry<String,Integer> entry = iterator.next();
    System.out.println(entry.getKey() + "--->" + entry.getValue());
}

11.3 custom generic structure

11.3.1 declaration of generics

Interface list < T > and class gentest < K, V >, where t, K and V do not represent values, but represent types. Any letter can be used here. It is commonly represented by T, which is the abbreviation of Type

11.3.2 instantiation of generics

  • Be sure to specify the value (type) of the type parameter after the class name. For example:

    • List<String> strList = new ArrayList<String>();

    • Iterator<Customer> iterator = customers.iterator();

  • T can only be a class and cannot be filled with basic data types. However, it can be filled with wrapper classes

  • Limiting the content of a collection to a specific data type is the core idea behind generics

11.3.3 custom generic classes and generic interfaces

  • A generic class may have multiple parameters. In this case, multiple parameters should be placed together in angle brackets. For example: < E1, E2, E3 >

  • The constructor of generic class is as follows: public GenericClass() {}

  • After instantiation, the structure of the original generic location must be consistent with the specified generic type

  • References with different generics cannot be assigned to each other

    • Although ArrayList < string > and ArrayList < integer > are two types at compile time, only one ArrayList is loaded into the JVM at run time
  • If a generic type is not specified, it will be erased. The type corresponding to the generic type is treated as Object, but it is not equivalent to Object

  • If the generic structure is an interface or abstract class, you cannot create an object of the generic class

class GenericTest {
public static void main(String[] args) {
    // 1. When used: similar to Object, but not equivalent to Object
    ArrayList list = new ArrayList();
    // list.add(new Date());// At risk
    list.add("hello");
    test(list);// Generic erasure, compilation does not type check
    // ArrayList<Object> list2 = new ArrayList<Object>();
    // test(list2);// Once an Object is specified, the compilation will type check and must be handled according to the Object
    }
    public static void test(ArrayList<String> list) {
        String str = "";
        for (String s : list) {
            str += s + ","; 
        }
        System.out.println("element:" + str);
    } 
}
  • The generic type declared on the class / interface represents a type in this class or interface, and can be used as the type of non static attribute, parameter type of non static method and return value type of non static method. But you cannot use generics of classes in static methods

  • Exception class cannot be generic

  • The parent class has generics, and the child class can choose to keep generics or specify generic types

    • Subclasses do not retain the genericity of the parent class: on-demand implementation
      • No type erase
      • Specific type
    • Subclasses retain the genericity of the parent class: generic subclasses
      • remove none
      • Partial retention
class Father<T1, T2> {
}
// Subclasses do not retain the generics of the parent class
// 1) No type erase
class Son1 extends Father {// Equivalent to class son extends father < object, Object >{
}
// 2) Specific type
class Son2 extends Father<Integer, String> {
}
// Subclasses retain the generics of the parent class
// 1) Keep all
class Son3<T1, T2> extends Father<T1, T2> {
}
// 2) Partial retention
class Son4<T2> extends Father<Integer, T2> {
}

11.3.4 custom generic methods

  • Method can also be generalized, regardless of whether the class defined in it is a generic class or not.
  • Generic parameters can be defined in generic methods. In this case, the type of parameter is the type of incoming data
  • Format of generic method:
    • Exception thrown by [access permission] < generic > return type method name ([generic ID parameter name])
public class Order<T> {

    String orderName;
    int orderId;

    //The internal structure of the class can use the generics of the class
    T orderT;

    public Order(){}

    public Order(String orderName, int orderId, T orderT) {
        this.orderName = orderName;
        this.orderId = orderId;
        this.orderT = orderT;
    }

    public String getOrderName() {
        return orderName;
    }

    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }

    public int getOrderId() {
        return orderId;
    }

    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }

    //None of the following three methods are generic methods
    public T getOrderT() {
        return orderT;
    }

    public void setOrderT(T orderT) {
        this.orderT = orderT;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderName='" + orderName + '\'' +
                ", orderId=" + orderId +
                ", orderT=" + orderT +
                '}';
    }

    //Generics of classes cannot be used in static methods
//    public static void show(T orderT) {
//        System.out.println(orderT);
//    }

    //Generic method: the generic structure appears in the method, and the generic parameters have nothing to do with the generic parameters of the class
    //In other words, it doesn't matter whether the generic method belongs to a generic class or not
    //Generic methods: can be declared static. Reason: generic parameters are determined when the method is called. Not determined when instantiating a class
    public static <E> List<E> copyFromArrayToList(E[] arr) {
        ArrayList<E> list = new ArrayList<>();
        for (E e: arr) {
            list.add(e);
        }
        return list;
    }
}

11.4 embodiment of generics in inheritance

  • Although class A is the parent of class B, G < a > and G < b > have no child parent relationship, and they are juxtaposed

    List<Object> list1 = null;
    List<String> list2 = null;
    //At this time, the types of list1 and list2 do not have a child parent relationship
    //list1 = list2;
    
  • Class A is the parent of class B. at this time, a < g > and B < g > have a child parent relationship

    List<String> list1 = null;
    ArrayList<String> list2 = null;
    list1 = list2;
    

11.5 use of wildcards

  • Wildcard:?

  • Class A is the parent class of class B. g < a > and G < b > have no relationship. Their common parent class is g <? >

    @Test
    public void test3() {
        List<Object> list1 = null;
        List<String> list2 = null;
    
        List<?> list = null;
    
        list = list1;
        list = list2;
    
        List<String> list3 = new ArrayList<>();
        list3.add("AA");
        list3.add("BB");
        list3.add("CC");
        list = list3;
        print(list3);
        print(list);
        //Add: for list <? > You can't add data to it
        //In addition to adding null
        //list.add("DD");
        list.add(null);
    
        //Get (read): run to read data. The read data is Object
        Object o = list.get(0);
        System.out.println(o);
    }
    
    public void print(List<?> list) {
        Iterator<?> iterator = list.iterator();
        for (;iterator.hasNext();) {
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }
    
  • Use of restricted wildcards

    • ? extends Person: G<? Extensions a > can be used as a parent of G < a > and G < b >, where B is a subclass of A

    • ? super Person: G<? Super a > can be the parent of G < a > and G < b >, where B is the parent of A

      @Test
      public void test4() {
          List<? extends Person> list1 = null;
          List<? super Person> list2 = null;
      
          List<Student> list3 = null;
          List<Person> list4 = null;
          List<Object> list5 = null;
      
          list1 = list3;
          list1 = list4;
          //list1 = list5;
      
          //list2 = list3;
          list2 = list4;
          list2 = list5;
      
          //Read data:
          list1 = list4;
          Person p = list1.get(0);
      
          list2 = list4;
          Object object = list2.get(0);
      
          //Write data
          //list1.add(new Student());// Compilation failed
          list2.add(new Student());
          list2.add(new Person());
      }
      
      class Person {}
      
      class Student extends Person {}
      
  • Cannot be used on a generic method declaration. Cannot use < > before the return value type?

    public static <?> void test(ArrayList<?> list){}
    
  • Cannot be used on declarations of generic classes

    class GenericTypeClass<?>{}
    

Keywords: Java JavaSE

Added by lanbor on Thu, 20 Jan 2022 20:08:24 +0200