preface
The first time you’re exposed to Java, compiling once, running everywhere, it feels powerful and must be sunk. But now the mainstream use of Java or the back-end of the scene, graphical interface development is not good at. Java’s continued dominance in the competition for back-end languages has a lot to do with the Java ecosystem, but there’s no denying that Java is reliably stable in high-concurrency scenarios. I also read an evaluation of golang language today and am ready to consider it as a technical reserve under entry. When I have time to study, I must study more.
Recently decided to spend some time duking up Java and decided to take a look at the JDK source code to the next level. I also want to write a series of blogs about Java and SpringBoot.
The generic
JDK 1.5 before
When I went into Java, it was JDK 1.7. But generics are a good thing. Before generics we might have written code like this
@Test
public void run1(a) {
// There is a collection where you want to store String data
List list =new ArrayList();
list.add("1111");
String o = (String) list.get(0);
System.out.println(o.length());
// May cause other developers to store ints
list.add(2222);
}
Copy the code
Problems with the above code:
- The elements stored in the collection need to be cast to use the corresponding Api.
- Compile-time syntax does not detect the problem I mentioned, which is potentially dangerous at run time
JDk 1.5
1.7 added features of rhombus generics that I doped together
// There is a collection where you want to store String data
List<String> list =new ArrayList();
list.add("1111");
String s = list.get(0);
System.out.println(s.length());
// The following error will be reported at compile time
// list.add(2222);
Copy the code
Isn’t Big Ben less anti-human
The generic
Generics: Parameter typing
- Generics can be declared on a class or method, and generics on a method take precedence over generics on a class. It is best not to declare the same name on a class for ease of understanding.
- Static methods cannot be declared with generic declarations on a class, only on a method
- Common generic declarations (T, E, K, V,?)
- ? Represents an indeterminate Java type
- T (type) indicates a specific Java type
- K and V are key values in Java key values
- E stands for Element
- S, U, V, etc. : the second, third, and fourth types in the multi-parameter case
Code validation
- Generics can be declared on a class or method, and generics on a method take precedence over generics on a class
public class ClientTest<T> {
/** * verify that generics can be declared on classes and methods * not so
*/
public <T2 extends ArgsParent> T2 run2(T k) {
System.out.println(k.getName());
System.out.println(k);
return(T2) k; }}Copy the code
This validates that generics can be declared on classes and methods
package com.fly.study.java.generics;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/ * * *@authorZhang qin * climbing@dateThe 2019-09-16-00:04 *@descriptionGeneric validation */
public class ClientTest<T> {
private ClientTest clientTest;
private Parent parent;
private Son son;
private ClientTest<Son> sonClientTest;
private ArgsParent argsParent;
private ArgsSon argsSon;
/** * limits the generics and return value types of method arguments. Generics take precedence over methods that do not use class *
public <T extends ArgsParent, T2 extends ArgsParent> T2 run2(T k) {
System.out.println(k.getName());
System.out.println(k);
return (T2) k;
}
@Before
public void before(a) {
clientTest = new ClientTest();
parent = new Parent();
parent.setName("parent");
son = new Son();
son.setAge(18);
sonClientTest = new ClientTest<>();
argsParent = new ArgsParent();
argsParent.setName("argsParent");
argsSon = new ArgsSon();
}
@Test
public void test2(a) {
System.out.println(clientTest.run2(argsParent));
System.out.println(clientTest.run2(argsSon));
// Verify that generics on methods take precedence over generics on classes
sonClientTest.run2(argsSon);
// The following is incorrect
// sonClientTest.run2(son);}}@Data
public class ArgsParent {
private String name;
}
@Data
public class ArgsSon extends ArgsParent {
private Integer age;
}
@Data
public class Parent {
private String name;
}
@Data
public class Son extends Parent {
private Integer age;
}
Copy the code
I’m using the same generic T on my class and on my method, but with different type constraints, the generic T on my class is ClientTest on my new object sonClientTest, and I’m specifying T on my method, when I run my method, Verify my conclusion if the argument can only be passed to ArgsParent and its subclasses.
// public class ClientTest<T>
// public <T extends ArgsParent, T2 extends ArgsParent> T2 run2(T k)
ArgsSon is a subclass of ArgsParent
sonClientTest.run2(argsSon);
// son is an instance of son
// sonClientTest.run2(son);
Copy the code
- Static methods cannot be declared with generics on a class, only on a method
public class ClientTest<T> {
/** * static methods can not use generics on the class, can only be declared on the method */
public static <T extends ArgsParent, T2 extends ArgsParent> void run4(T k) {
System.out.println(k);
}
// Syntax error
public static void run4(T k) { System.out.println(k); }}Copy the code
- Generic qualifier
Generic qualifiers are easy to understand literally; comments in the code will tell you what they mean
JDK 1.8 <S super ArgsParent> < ArgsParent <? Extends ArgsParent> // limits arguments to ArgsParent and its parent <? extends ArgsParent>Copy the code
public class AllGenerics<T> {
public void run1(T t) {
System.out.println(t);
}
public <S> void run2(S s) {
System.out.println(s);
}
// Restrict the argument type to ArgsParent and its subclasses
public <S extends ArgsParent> void run3(S s) {
System.out.println(s);
}
// Syntax error,
// public <S super ArgsParent> void run3(S s) {
// System.out.println(s);
/ /}
// Restrict the argument type to ArgsParent and its subclasses
public void run4(List
s) {
System.out.println(s);
}
// Limit arguments to ArgsParent and its parent class
public void run5(List<? super ArgsParent> s) { System.out.println(s); }}Copy the code
Generic erasure
Generics are valid only at compile time, after which the generic declaration is replaced. For certain types, Object is used, and for uncertain ones.
- When a generic type cannot be determined
/ / the source code
public class AllGenerics<T> {
public void run1(T t) { System.out.println(t); }}// The compiled code can be interpreted like this
public class AllGenerics<Object> {
public void run1(Object t) { System.out.println(t); }}Copy the code
- Use generic qualifiers for
public class AllGenerics<T> {
public <S extends ArgsParent> void run2(S s) { System.out.println(s); }}// The compiled code can be interpreted like this
public class AllGenerics<ArgsParent> {
public void run1(ArgsParent t) { System.out.println(t); }}Copy the code
Code validation
- Generics are only valid at compile time
@Data
public class ClientTestSuperT {
@Test
public void test1(a) throws Exception{
List<String>t=new ArrayList<>();
Method add = t.getClass().getMethod("add",Object.class);
// Add an Integer number
add.invoke(t,1); System.out.println(t); }}Copy the code
- Generic erasure uses an identifiable type replacement
package com.fly.study.java.generics;
import org.junit.Test;
import java.lang.reflect.Method;
public class AllGenerics<T> {
public <S extends ArgsParent> void run2(S s) {
System.out.println(s);
}
public void run1(T t) {
System.out.println(t);
}
@Test
public void test1(a) throws Exception {
AllGenerics<String> allGenerics =new AllGenerics<>();
Method method= allGenerics.getClass().getMethod("run1", Object.class);
// java.lang.NoSuchMethodException:
// com.fly.study.java.generics.AllGenerics.run1(java.lang.String)
// Method method= allGenerics.getClass().getMethod("run1", String.class);
method.invoke(allGenerics,"111");
}
@Test
public void run2(a) throws Exception {
AllGenerics<String> allGenerics =new AllGenerics<>();
Method method= allGenerics.getClass().getMethod("run2", ArgsParent.class);
ArgsParent argsParent = new ArgsParent();
argsParent.setName("Test");
// java.lang.NoSuchMethodException:
// com.fly.study.java.generics.AllGenerics.run1(java.lang.String)
// Method method= allGenerics.getClass().getMethod("run2", Object.class);method.invoke(allGenerics,argsParent); }}Copy the code
- Verify the train of thought
AllGenerics<Object>Public void run1(Object t)
public void run1(T t) {
System.out.println(t);
}
Public void run2(ArgsParent s)
public <S extends ArgsParent> void run2(S s) {
System.out.println(s);
}
Copy the code
- Method run1 can be obtained by reflection. Method run1 can be obtained by reflection. Method run1 cannot be found by reflection
@Test
public void test1(a) throws Exception {
AllGenerics<String> allGenerics =new AllGenerics<>();
Method method= allGenerics.getClass().getMethod("run1", Object.class);
method.invoke(allGenerics,"111");
}
Copy the code
The above code works fine, verifying that the code was actually replaced after compilation
@Test
public void test1(a) throws Exception {
AllGenerics<String> allGenerics =new AllGenerics<>();
Method method= allGenerics.getClass().getMethod("run1", String.class);
method.invoke(allGenerics,"111");
}
Copy the code
The operating error code Java. Lang. NoSuchMethodException: com. Fly. Study. Java generics. AllGenerics. Run1 (Java. Lang. String), explain the compiled code there is no this way
- For generics that use qualified types, replace them with qualified types
Public void run2(ArgsParent s)
public <S extends ArgsParent> void run2(S s) {
System.out.println(s);
}
Copy the code
@Test
public void run2(a) throws Exception {
AllGenerics<String> allGenerics =new AllGenerics<>();
Method method= allGenerics.getClass().getMethod("run2", ArgsParent.class);
ArgsParent argsParent = new ArgsParent();
argsParent.setName("Test");
method.invoke(allGenerics,argsParent);
}
Copy the code
The method obtained above shows that my guess is correct
@Test
public void run2(a) throws Exception {
AllGenerics<String> allGenerics =new AllGenerics<>();
ArgsParent argsParent = new ArgsParent();
argsParent.setName("Test");
Method method= allGenerics.getClass().getMethod("run2", Object.class);
method.invoke(allGenerics,argsParent);
}
Copy the code
Code error, cannot find corresponding method
Recommended reading
Java generics understanding
Generics: How they work and why they’re important