Generic Notes

Generic programming
A generic class that stores a key-value

public class Entry<K,V>{
    private K key;
    private V value;

    public Entry(K key,V value){
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }
}

It is worth noting that:

Entry<String, int > a; // Cannot be instantiated with a basic type, int is a basic type, you need to use Integer 
Entry<String,Integer> entry = new Entry<>("www",123);

generic method

public  class Arrays {
     public  static <T> void swap(T[] array, int i, int j){ // When declaring a generic method, the type parameter should be placed after the modifier (public, static). 
        T temp = array[i]; before return type
        array[j] = array[i];
        array[i] = temp;
    }
}

The Arrays.swap method can swap any array element (as long as the element type in the array is not a primitive type).
type qualification

public  static <T extends AutoCloseable> void closeAll(ArrayList<T> elems) // If there are multiple limits with & connection, such as T extend AutoCloseable & Runnable 
    throws Exception{
     for (T elem:elems) elem.close();
}

extends AutoCloseable ensures that elem.close is valid because the element type is a subtype of AutoCloseable.

try {
    Arrays.closeAll( new ArrayList<String>()); // Not feasible because String is not a subclass of AutoCloseable 
} catch (Exception e){
    e.printStackTrace ();
}

Type mutation and wildcard
array can perform type mutation. For example, the Manager class is a subclass of Employee, and the Manager[] array can be passed to Employee[];
type mutation cannot be performed on array lists. If ArrayList<Manager> is assigned to ArrayList<Employee >, the following situations exist.

ArrayList<Manager> bosses = new ArrayList<>();
ArrayList <Employee> emls = bosses; // Illegal, but assuming it 
works empls.add( new Employee(...)); // Then an ordinary employee will exist in bosses
 // If a method never writes to the array operation, it will not destroy the array list, you can express this situation with wildcards 
public  static  void printNames(ArrayList<? extends Employee> staff){ // No matter what type, ? Both indicate that it is a subtype of Employee, so staff.get(i).getName() can be executed. 
    for ( int i=0;i<staff.size();i++ ){
        System.out.println(staff.get(i).getName());
    }
}

It is worth noting that the add method cannot be used because ? Can represent any subclass.
supertype wildcard

? super Employee represents a supertype of Employee

public static void printAll(Employee[] staff, Predicate<? super Employee> filter){//
    for(Employee e:staff){
        if(filter.test(e)){
            System.out.println(e.getName());
        }
    }
}

Employee.printAll(new Employee[1],employee -> employee.toString().length()%2==0);
//Predicate interface is fixed, between Predicate<Employee> and Predicate<Object> There is no relationship, so the parent type of Employee <? super Employee>
PECS: produce (producer) extends, consumer (consumer) super. Reading the value from ArrayList is the producer, using extends. If Predicate is used for testing, it is the consumer, using super
wildcard with type variable

The definition of Collections.sort():
public static <T extends Comparable<? super T>> void sort(List<T> list)//The reason for using <? super T> here is to prevent the restrictions of Comparable from being too strict. When subtypes inherit supertypes, unexpected effects can occur.
The sort method can sort any List<T> as long as T is a subtype of Comparable, and the Comparable interface is also generic

public interface Comparable<T>{
    int compareTo(T other);
}
Unlimited wildcards
public  static  boolean hasNull(ArrayList<?> objects){ // The element type doesn't matter, you can also use generic methods to implement 
    for (Object e:objects){
         if (e == null ){
             return  true ;
        }
    }
    return false;
}

 

Generics in the Java Virtual Machine The
Java language designers decided to implement "wipe" types from the virtual machine, prompting users to use generics.
Type erasure. When compiling, the generic type will be compiled into the original type, such as the generic type of the top Entry class, which will be
inserted by the compilation city Object conversion, that is, compiled into Object, but the return value will be coerced, such as String key = (String) entry.getKey(); Object type is cast to String type

Generic constraints
1. An ArrayList<int> cannot be generated without basic type parameters
2. All types are primitive at runtime, that is, an ArrayList cannot be queried at runtime whether it contains a String object. That is, if(a instanceof ArrayList<String>)//Illegal
It is also invalid to convert to a generic type, but it is legal

Object result = new ArrayList<String>();
    ArrayList<String> list = (ArrayList<String>)result;//
    @SuppressWarnings("unchecked") ArrayList<String> list = (ArrayList<String>)result;

Misuse of @SuppressWarnings can cause heap pollution - an instance object that should belong to a specific generic type actually belongs to a different generic type, for example, you can assign an ArrayList<Employee> to an ArrayList<String> reference. As a result, when an error element is retrieved, a ClassCastException will be thrown
3. The type variable cannot be instantiated

    public static <T> T[] repeat(int n,T obj){
        T[] result = new T[n]; // Illegal, you cannot construct an array with new T[...] 
        for ( int i=0;i<n;i++ ){
            result[i] = obj;
        }
        return result;
    }
    Constructed by reflection mechanism, refer to the copy array code of the reflection chapter
    public static <T> T[] repeat(int n,T obj){
        Class<?> c = obj.getClass();
        Object newArray = Array.newInstance(c,n);
        for(int i=0;i<n;i++){
            Array.set(newArray,i,obj);
        }
        return (T[])newArray;
    }

It is worth noting that ArrayList can be instantiated using type variables, ie ArrayList<T> result = new ArrayList<>();//Legal

4. Cannot construct an array of parameterized types

Entry<String ,Integer>[] entries = new Entry<String,Integer>[100]; // Illegal, because after type erasure, the array constructor will create a primitive Entry array, you can add any object 
    Entry<String ,Integer>[] entries2 = (Entry<String, Integer>[]) new Entry<?,?>[100]; // Legal, cast to the corresponding type

Easier is to construct an array list.
5. The class type variable in the static context is not valid,
that is, the type variable cannot be used in static variables or static methods. 6. The method after type erasure
may conflict .
Object's own methods conflict
7. Exceptions and generics
cannot throw or capture a generic class object, and cannot even build a generic subclass of Throwable
public class Problem<T> extends Exception//Illegal--generic Class cannot be a subclass of Throwable
Generic variables cannot be used in catch clauses

Reflection and generic
Class<T> class
public Class<T>{
public T newInstance() throws...{...}
}
directly returns an object of type T, eliminating the need for a conversion.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325698936&siteId=291194637