preface

Java generics is a new feature introduced in J2SE1.5, its essence is parameterized type, that is, the data type being operated is specified as a type parameter (type parameter). This parameter type can be used in the creation of classes, interfaces and methods, respectively called generic classes, generic interfaces and generic methods. Let’s look at these questions to understand Java generics.

  1. What are generics for?
  2. Why generics?
  3. What is generic erasure?
  4. What is a wildcard?
  5. What is the upper boundary? What is the lower boundary?

The role of generics

First question, what are generics for? In a nutshell, make it possible to pass types like method parameters.

2. Why generics?

So why generics appear, and what problems they solve. For example, now we have a water tank, and we put a red carp in it.

// Red carp object
public class GreenCarp {
    public void move(a) {
        System.out.println("The green carp are blowing bubbles!"); }}// Water tank object
public class Tank {
    private RedCarp redCarp;

    public RedCarp getRedCarp(a) {
        return redCarp;
    }

    public void setRedCarp(RedCarp redCarp) {
        this.redCarp = redCarp; }}/ / put the fish
public class Test {
    public static void main(String[] args) {
        Tank tank = new Tank();
        tank.setRedCarp(newRedCarp()); tank.getRedCarp().move(); }}Copy the code

Then we want to change the water tank into green carp. At this time, someone may directly define an Object in the water tank Object.

public class Tank {
    private Object obj;

	public Object getObj(a) {
		return obj;
	}

	public void setObj(Object obj) {
		this.obj = obj; }}public class Test {
    public static void main(String[] args) {
        Tank tank = new Tank();
        tank.setObj(new RedCarp());
        ((RedCarp) tank.getObj()).move();
        tank.setObj(newGreenCarp()); ((GreenCarp) tank.getObj()).move(); }}Copy the code



There seems to be no problem, but if Object is used too much, it will become very troublesome for programmers. For example, it might not convert to the correct type, but the compiler won’t explode! Error after run!

public class Test {
    public static void main(String[] args) {
        Tank tank = new Tank();
        tank.setObj(new RedCarp());
        ((RedCarp) tank.getObj()).move();
        tank.setObj(new GreenCarp());
        ((RedCarp) tank.getObj()).move(); // Write RedCarp}}Copy the code



So, if we use generics, everything is different.

public class Tank<T> {
    private T t;

	public T getObj(a) {
		return t;
	}

	public void setObj(T t) {
		this.t = t; }}Copy the code

Generic erase

Before we talk about generic erasure, we can look at an example,

public class Test {
    public static void main(String[] args) {
    	List<String> l1 = new ArrayList<String>();
    	List<Integer> l2 = newArrayList<Integer>(); System.out.println(l1.getClass() == l2.getClass()); }}Copy the code

What do you think this code will output? true or false?



The answer is true. Why? Why the two run-time classes of L1 and L2 are equal.

That’s where generic erasure comes in.

Although the two objects look very different at coding time, they are already generically erased by reflection at runtime.

Example:

List<String> l1 = new ArrayList<String>();
l1.add("8848");
Class c = l1.getClass();
Method m = c.getMethod("add", Object.class);
m.invoke(l1, 8848);
System.out.println(l1);
Copy the code

Summary: Generic erasure is intended to be compatible with older JDK coding. Generics, on the other hand, exist only at compile time. Generics allow the compiler to check types at compile time to improve type safety and reduce runtime exceptions due to object type mismatches.

4 the wildcard

The wildcard?

Java inheritance relationships are not accepted in generics without any declarative modifications. So you need generics.

5 Upper and lower boundaries

The upper boundary

? The extends T represents a subclass type that can be passed T or T.

Under the border

? Super T means that the incoming type must be T or T’s parent.

When do we use the upper boundary?

You can’t put the upper boundary, because you don’t know what type to put on the upper boundary so you get an error, but you can take it.

When do we use lower bounds?

You can’t take the lower bound, because with the lower bound, you don’t know what kind of data you want to take out, but you can.