1: What is generics?
(1) Why use generics?
For example, the implementation in MyArray class can only save int type data, and other types of data, such as double, String or custom type objects, cannot be stored at all. All use generics.
(2) Definition: generics can write type independent code, that is, the written code can be reused by many different types of objects. It is often used in some general code implementations, such as collection < E >, list < E >, ArrayList < E >. This < E > is the type parameter, that is, generics.
(3) Essence: type parameterization. Similar to function parameter passing, passing different arguments will produce different results after the function is run.
2: Classification of generics
Classification: generic classes, generic methods, and generic interfaces.
(1) Generic class:
1. Syntax example:
class Generic class name<Type parameter list> { // Type parameters can be used here } class ClassName<T1, T2, ..., Tn> { // Class implementation }
2. Interpretation:
< type parameter > is generally represented by a capital letter. Common names are:
E stands for Element
K means Key
V means Value
N stands for Number
T means Type
S. U, V, etc. - second, third, fourth type
3. Examples of using generic class syntax:
// When implementing the MyArray generic class, the implementer does not care what type E represents // When instantiating a generic class, the compiler knows exactly what type E represents public class MyArray<E> { private E[] array = null; private int size; private int capacity; public MyArray(int capacity){ // Why new Object [], why strong conversion is required here, will be explained later array = (E[])new Object[capacity]; size = 0; this.capacity = capacity; } public void add(E data){ if(size < capacity) array[size++] = data; } public E get(int index){ return array[index]; } public int size(){ return size; } }
4. Instantiation of generic class:
Generic class variable name; Define a generic class reference. new generic class (constructor arguments); Instantiate a generic class object.
public static void main(String[] args) { // Instantiate the generic class with String type, indicating that only String type objects can be stored in m MyArray<String> m = new MyArray<>(10); m.add("Peter"); m.add("David"); m.add("Jim"); // Compilation failure: because it is clear that only String type objects can be stored inside when instantiating // Cannot convert between Person object and String object // m.add(new Person("Lily")); for(int i = 0; i < m.size(); ++i){ // The members obtained from m here do not need to be cast any more String s = m.get(i); System.out.print(s + " "); } }
Note: the types in the left < > cannot be omitted, and the types in the right < > can be omitted without writing types, but < > cannot be omitted
MyArray<String> m = new MyArray<>(10);
(2) Use of generic classes - wildcards
1. Definition:? For use in generics, that is, wildcards.
2. Code example:
public class MyArray<E> {...} // Any type of MyArray can be passed in public static void printAll(MyArray<?> m) { ... } // The following calls are correct printAll(new MyArray<String>()); printAll(new MyArray<Integer>()); printAll(new MyArray<Double>()); printAll(new MyArray<Number>()); printAll(new MyArray<Object>());
3. Wildcard - upper bound
Syntax:
<? extends upper bound>
Code example:
// The passed in type argument is MyArray of any type of Animal subclass public static void printAll(MyArray<? extends Animal> m) { ... } // The following calls are correct printAll(new MyArray<Cat>()); printAll(new MyArray<Dog>()); // The following call is a compilation error printAll(new MyArray<String>()); printAll(new MyArray<object>());
4. Wildcard - lower bound
Syntax:
<? super Lower bound>
Code example:
// You can pass in MyArray of any type whose type argument is a Cat parent class public static void printAll(MyArray<? super Cat> list) { ... } // The following calls are correct printAll(new MyArrayList<Cat>()); printAll(new MyArrayList<Animal>()); printAll(new MyArrayList<Object>()); // The following call is a compilation error printAll(new MyArrayList<String>()); printAll(new MyArrayList<Dog>());
(3) Parent-child types in generics (wildcard <? > is required to determine parent-child types)
1. MyArray < Object > is not the parent type of myArray < animal >
2. MyArray < animal > is not the parent type of myArray < cat >
4. MyArray<?> MyArray <? Parent type of extends animal >
5.MyArray<? Extends animal > is the parent type of myarraylist < dog >
3: Generic method
(1) Syntax format:
Method qualifier <Type parameter list> Return value type method name(parameter list ) { ... }
(2) Code example:
public class Util { public static <E> void swap(E[] array, int i, int j) { E t = array[i]; array[i] = array[j]; array[j] = t; } } // There is no explicit type specified. Type push is required during compilation Integer[] a = { ... }; swap(a, 0, 9); String[] b = { ... }; swap(b, 0, 9); // Type is specified explicitly. Type derivation is not required during compilation Integer[] a = { ... }; Util.<Integer>swap(a, 0, 9); String[] b = { ... }; Util.<String>swap(b, 0, 9);
4: Advantages and disadvantages of generics
(1) Advantages:
1. Improve code reusability
2. Improve development efficiency
3. Some general types of containers or algorithms can be implemented
(2) Disadvantages:
1. Generic type parameters do not support basic data types
2. Cannot instantiate an object of generic type
3. Static properties cannot be declared using generic types
4. instanceof cannot be used to judge generic types with type parameters
5. Cannot create generic class array
6. Cannot create, catch, throw a generic class exception (exception does not support generics)
7. Generic type is not part of formal parameter and cannot be overloaded