1. What is java generics?
java generics: the English name is generics. Generics is a new feature introduced by jdk5. The essence of java generics is parameterized types, that is, all operation data types are specified as a parameter. Entities that operate on parameterized types, such as classes, interfaces, or methods, are called generic entities.
2. java generic class
Generic class: must be declared before use; The declaration is through < T, E,... > Achieved; Convention generics can be represented by a single uppercase letter T, E, K, V, and so on
import java.lang.reflect.Field; public class GenericsSimpleExample { public static void main(String[] args) { A<String , Integer> a0 = new A<>(); a0.t= "testStr"; A<Integer , Integer> a1 = new A<>(); a1.t = 100; // Generic parameters should refer to data types when used, not basic data types, such as int, etc //A<Integer , int> a2 = new A<>(); // If a generic class does not specify a specific parameter type, the default data type is object Class<A> cls = A.class; Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName() + ":" + field.getType().getSimpleName()); } // Different data types can be seen in the specific implementation of generic classes. In practice, they are the same data types, which can be verified by hashcode System.out.println(a0.getClass().hashCode()); System.out.println(a1.getClass().hashCode()); } static class A <T , E> { public T t; public void test0(T t) { } } }
Key points:
- The parameter type of a generic class cannot be a basic data type. Use a reference data type
- When a generic class does not specify a specific data type, it uses the object type by default
- Generic classes can use different data types, which are actually the same data types
3. Subclasses derived from generic classes
- 1. If the subclass is generic, the subclass should be consistent with the generic type of the parent class
class A<T> extends B<T>{}
- 2. If the subclass is not generic, the parent class should specify the generic data type
class A extends B<String>{}
4. Generic interface
Generic interface syntax:
interface Interface name <Generic identity,Generic identity, ...>{ Generic identity method name(); ... }
- 1. The implementation class is also a generic class, and the generic type should be consistent with the interface
interface B <T,V> {} class A<T,V> implements B<T,V>{}
- 2. The implementation class is not a generic class, and the interface should specify a specific type
class B implements B<String,Integer>{}
5. Generic method
Generic method syntax:
Modifier <T,E,...> Return value type method name (parameter list ){ Method body; }
Generic method characteristics:
- Only the method that declares < T > is a generic method. Only the generic method used for parameter passing is not a generic method
- Like generic classes, you can use K, V, T, E, and so on to represent generics
public class GenericsMethodExample { public static void main(String[] args) { A0 a0 = new A0(); a0.test0("hello"); A1<Integer> a1 = new A1<>(); a1.test("hi", "hello"); A1.test1("hello world"); } static class A0 { public <T, E> T test0(T t) { System.out.println("t = " + t); return null; } } static class A1<K> { /** * When the type of generic method is consistent with that of generic class, the of specific method shall prevail * @param k * @param t */ public <T, K> T test(T t , K k) { System.out.println("t = " + t); System.out.println("k = " + k); return null; } /** * static Method must be specified as a generic method plus {@ code < k >} * @param k */ public static <K> void test1(K k) { } } }
induce:
- When the type of generic method is consistent with that of generic class, the of specific method shall prevail
- To use generics for static methods, you must specify a generic method plus
6. Generic wildcard
Type wildcards are generally used? Instead of specific type arguments, type wildcards are type arguments, not type parameters
public class GenericsWildcardExample { public static void main(String[] args) { A<String> a0 = new A<>(); show(a0); A<Integer> a1 = new A<>(); show(a1); } public static void show(A<?> a){ System.out.println(a.getClass()); } static class A<T> { } }
7. Type wildcard upper limit
Syntax:
class/Interface <? extends actual argument >
It is required that the modified generic type can only be an argument type or a subclass type of an argument
public class GenericsWildcardExample { public static void main(String[] args) { A<A1> a11 = new A<>(); A<A2> a12 = new A<>(); A<A3> a13 = new A<>(); // Only A2 and its subclasses can be used show0(a12); show0(a13); } public static void show0(A<? extends A2> a) {} static class A<T> { } static class A1{} static class A2 extends A1{} static class A3 extends A2{} }
8. Type wildcard lower limit
Syntax:
class/Interface <? super actual argument >
It is required that the modified generic type can only be the argument type or the parent type of the argument
public class GenericsWildcardExample { public static void main(String[] args) { A<A1> a11 = new A<>(); A<A2> a12 = new A<>(); A<A3> a13 = new A<>(); // Only A2 and its parent classes can be used show1(a11); show1(a12); } public static void show1(A<? super A2> a){} static class A<T> { } static class A1{} static class A2 extends A1{} static class A3 extends A2{} }
9. What is generic erasure?
Generic information only exists in the code compilation stage. Before entering the JVM, the information related to generics will be erased
Drop, we call it type erase
9.1 unlimited type erasure
import java.lang.reflect.Field; public class GenericsWipeExample { public static void main(String[] args) { Class<?> cls0 = A.class; Field[] fields = cls0.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName() + ":" + field.getType().getSimpleName()); } } static class A <T>{ T t; } }
Print:
t:Object
9.2 limited type erasure
import java.lang.reflect.Field; public class GenericsWipeExample { public static void main(String[] args) { Class<?> cls1 = A1.class; Field[] fields1 = cls1.getDeclaredFields(); for (Field field : fields1) { System.out.println(field.getName() + ":" + field.getType().getSimpleName()); } } static class A1<T extends Number> { T t; } }
Print:
t:Number
9.3 method type
import java.lang.reflect.Method; public class GenericsWipeExample { public static void main(String[] args) { Class<?> cls2 = A2.class; Method[] methods = cls2.getDeclaredMethods(); for (Method method : methods) { System.out.println(method.getName() + ":" + method.getReturnType().getSimpleName()); } } static class A2<T extends Number> { T t; public <K extends Number> K test(K k) { return null; } } }
test:Number
9.4 bridging method
interface MyInter<T>{ T fun1(); } class DD implements MyInter<String>{ @Override public String fun1() { return null; } }
import java.lang.reflect.Method; public class GenericsWipeExample { public static void main(String[] args) { Class<?> cls3 = A3.class; Method[] methodss = cls3.getDeclaredMethods(); for (Method method : methodss) { System.out.println(method.getName() + ":" + method.getReturnType().getSimpleName()); } } interface MyInter<T>{ T test(); } class A3 implements MyInter<String> { @Override public String test() { return null; } } }
Print:
test:String
test:Object
10. Generics and reflection
Class<?> cls0 = A.class; Field[] fields = cls0.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName() + ":" + field.getType().getSimpleName()); }