summary
What is generics? What problems can generics solve?
Generics, or parameterized types, make your program easier to read and safer.
Before Java added generic features [before JDK5], the design of generic programs was implemented by inheritance. The following program can be compiled and run normally, but casting the result of get will produce an error. In order to solve this problem, generics came into being.
/** * Elements of different types are add ed to the ArrayList */ @Test public void mixedValueTest(){ ArrayList mixedValue = new ArrayList(); mixedValue.add(1L); mixedValue.add("string"); mixedValue.forEach(item->{ System.out.println((String)item); }); } // java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String
During the use of generics, the data type of the operation is specified as a parameter. This parameter type can be used in classes, interfaces and methods, which are called generic classes, generic interfaces and generic methods respectively.
characteristic
Generics are only effective in the compilation stage. During compilation, de genericization measures will be taken: erase the information related to generics, and add type checking and type conversion methods at the boundary of objects entering and leaving methods. That is, generic information will not enter the run-time phase.
/** * Use type parameters to constrain the type of an element */ @Test public void traitTest(){ ArrayList<String> stringList = new ArrayList<String>(); stringList.add("string a"); stringList.add("string b"); ArrayList<Integer> IntegerList = new ArrayList<Integer>(); IntegerList.add(100); IntegerList.add(200); if(stringList.getClass()==IntegerList.getClass()){ System.out.println("A generic type can logically be regarded as many different types, but in fact they are the same type"); } }
Definition and use of generics
There are three ways to use generics: generic classes, generic interfaces, and generic methods.
Generic class
Generic types are used in the definition of classes and are called generic classes. When instantiating a generic class, you need to pass in the generic type argument [no, the default is Object]. The most typical container classes are List, ArrayList, Set and Map.
1. Definition of generic class class Class name <Generic identification: you can write any identification number to identify the type of the specified generic>{ private Generic identification variable name; ..... } } Common Generic identification [generally use capital letters]: K/V/T/E/U/S/R...... 2. Use of generic classes // Generics are equivalent to factories of ordinary classes Category<Specific data types> Object name = new Class name<Specific data types[JDK7 Can be omitted after]>(); 3. Subclasses derived from generic classes // A subclass is also a generic class. The generic types of the subclass and the parent class should be consistent and can only be extended on the basis of the parent class [the subclass must contain the generic ID of the parent class] class Subclass name<Generic identity:T> extends Parent class name<Generic identity:T> // The child class is not a generic class, and the parent class should specify the data type of the generic class class Subclass name extends Parent class name<Explicit data type>
matters needing attention:
- The type parameter of generic type can only be Object type, not basic data type
- If no specific data type is specified. The default operation type is Object
- A generic type can logically be regarded as many different types, but they are actually the same type
generic interface
The definition and use of generic interfaces and generic classes are basically the same.
1. Definition of generic interface interface Interface name<Generic identification: you can write any identification number to identify the type of the specified generic>{ private Generic identity method name(); ..... } 2. Use of generic interfaces // The implementation class is a generic class, and the generic types of the implementation class and the interface are consistent class Implementation class<T> implements generic interface <T> // The implementation class is not a generic class, and the interface should specify the data type class Implementation class implements generic interface <String>
generic method
Generic method: it refers to the specific type of generic when calling the method. The generic ID in the generic method has nothing to do with the generic ID in the generic class and can be regarded as an independent system.
1. Generic method definition // The key is the diamond syntax after the modifier < E > Modifier <E> Return value type method name(E ele){ return Objects.isNull(ele); } // The diamond syntax after the modifier < E >, it can be understood that this method is declared as a generic method, and the generic member method of the generic class is not a generic method. 2. Generic methods and variable parameters public <E> void printElement(E... elements){ for(E element : elements){ System.out.println(element); } } 3. Use of generic methods printElement("string",100,true);
Summary:
- Generic methods can be methods that change independently of classes
- Whenever you can, you should try to use generic methods instead of generalizing classes
- If static methods want to use generic capabilities, they must be defined as generic methods because static methods cannot access the generics defined on the class.
wildcard
Generic identifiers are essentially wildcards, no difference. They are conventional things in coding.
Usually, T, E, K, V,? It is agreed as follows:
- ? Represents an ambiguous java type
- T (type) represents a specific java type
- K V (key value) respectively represents the Key Value in the java Key Value
- E (element) stands for Element
? Difference between and T
T is a definite type, which is usually used for the definition of generic classes and generic methods,? Is an uncertain type, which is usually used for the calling code and formal parameters of generic methods. It cannot be used to define classes and generic methods.
The consistency of generic parameters can be determined by T
// ? It is an uncertain element in itself, and there is no guarantee that the elements of the List are consistent void t1(List<? extends Number> list); // Make sure that the generic parameters are consistent and that the same elements are stored in the List void t1(List<T> list);
The type parameter T can be multi qualified, while the wildcard? no way
Wildcards can use superclass qualification, but type parameters cannot
T extends Number // allow T susper Number // not allow ? extends Number // allow ? susper Number // allow
Variable type qualification
Upper bound wildcard <? extends E>
The upper bound is declared with the extends keyword, indicating that the parameterized type may be the specified type and its subclasses:
// The restricted type argument implements the Comparable interface, where T represents the subtype of the restricted type and Comparable is the upper bound of the restricted type public static <T extends Comparable> T min(T... comparbleElements) // A type variable or wildcard can have multiple qualifications public static <T extends Comparable & Serializable> T min(T... comparableElements) public static <? extends Comparable & Serializable> T min(T... comparableElements)
Summary:
- If the type passed in is not a qualified type and its subclasses, the compilation will not succeed
- Use the extends wildcard to indicate that you can read but not write
Lower bound wildcard <? super E>
The lower bound is declared with super, indicating that the parameterized type may be the specified type and its parent type, up to Object.
The function of suspend keyword is opposite to that of extends keyword. Use <? Super integer > wildcard indicates:
- It is allowed to call the set(? super Integer) method to pass in the reference of Integer;
- Calling the get() method to get a reference to an Integer is not allowed.
The only exception is to get the reference of object: Object o = p.getxxx().
In other words, use? Super integer > wildcards are used as method parameters to indicate that the internal code of the method can only be written and cannot be read for parameters.
Compare the differences between extends and super wildcards:
- <? Extensions T > it is allowed to call the read method T get() to get the reference of T, but it is not allowed to call the write method set(T) to pass in the reference of T (except null)
- <? Super T > it is allowed to call the write method set(T) to pass in the reference of T, but it is not allowed to call the read method T get() to get the reference of T (except for getting Object).
One is to allow reading and no writing, and the other is to allow writing and no reading