directory

preface

1. The concept of generics

2. Use of generics

3, generic principle, generic erase

3.1 IDEA Viewing bytecode

3.2 Principles of generic erasure

4,? And T

5, super extends

6. Pay attention

Static methods do not have access to a class’s generics

Type cannot be changed after creation

3. Type judgment problem

4. Create type instances

7,


preface

 

Generics are advanced concepts in Java, but also necessary skills to build frameworks, such as all kinds of collection classes are implemented by generics, today we talk in detail about the concept of generics in Java, hope to gain something. Like it, follow it, share it.

1. The concept of generics

The purpose of generics is to parameterize types, known as type parameters

Public void fun(String s); The parameter is of type String and is fixed

Public static

void fun(T T); public static

void fun(T T); The type of the parameter is the type of T, and it’s not fixed

Common letters for generics are the following:

? T (type) represents a specific Java typeV (key value)Respectively represent Key values in Java Key valuesE (element)On behalf of the ElementCopy the code

These letters are used freely, just for types, but also for words.

2. Use of generics

Generics can be used in three ways: generic classes, generic interfaces, and generic methods.

Where classes are used

Where the method is used

  • Java generic class
  • Java generic methods
  • Java generic interfaces
/ * * *@authorParsley * /
public class Player<T> {/ / a generic class
  private T name;
  public T getName(a) {
      return name;
  }
  public void setName(T name) {
      this.name = name; }}Copy the code

 

public class Apple extends Fruit {
  public <T> void getInstance(T t){// Generic methodsSystem.out.println(t); }}Copy the code
public interface Generator<T> {
   
      public T next(a);
   
  }
Copy the code

3, generic principle, generic erase

3.1 IDEA Viewing bytecode

Create a Java file, compile it, and verify that the class is generated

2. Idea -> Java file ->View

3.2 Principles of generic erasure

Let’s look at an example, starting with a non-generic version:

As you can see from the bytecode, we cast the object when we fetch it.

Here’s a generic version, from a bytecode point of view:

Information about type variables is available during compilation. Therefore, the set method can be checked by the compiler, and invalid types cannot be compiled. For the GET method, however, the actual reference type at run time is of type Object because of the erasing mechanism. To “restore” the type of the result returned, the compiler adds type conversions after GET. So, in player. class file, there is a type conversion logic in line 18 of the main method body. It was added automatically by the compiler for us.

So we do something for us where the generic class objects are read and written, adding constraints to the code.

A generic parameter will be erased to its first boundary (there can be more than one boundary, using the extends keyword to add a boundary to the parameter type). The compiler actually replaces the type parameter with the type of its first boundary. If no boundary is specified, the type parameter is erased to Object.

4,? And T

? Use scenarios like Object and C++ Void Pointers are basically indeterminate types that can point to any Object. Usually used in reference.

T is the defining type of the generic, and at run time is the definitive type.

5, super extends

Wildcard qualification:

: A wildcard qualification for a subtype, primarily query, such as a consumer collection scenario

: Wildcard qualification of a supertype, mainly added, such as producer set scenarios

Super wildcard, backward compatible with subclasses and their descendants, T super Child is erased to Object

Extends extends wildcard extends Parent is erased to Parent, which is compatible with subclasses and their descendants


class Fruit {}
class Apple extends Fruit {}
class FuShi extends Apple {}
class Orange extends Fruit {}

import java.util.ArrayList;
import java.util.List;

public class Aain {
 public static void main(String[] args) {
       / / the upper bound
       List<? extends Fruit> topList = new ArrayList<Apple>();
       topList.add(null);
       // The add Fruit object will report an error
       //topList.add(new Fruit());
       Fruit fruit1 = topList.get(0);

       / / lower
       List<? super Apple> downList = new ArrayList<>();
       downList.add(new Apple());
       downList.add(new FuShi());
       // The get Apple object will report an error
       //Apple apple = downList.get(0);
}
Copy the code

The upper bound <? Extend Fruit>, all the subclasses that extend Fruit, but which subclass, but Fruit

Lower bound <? Super Apple>, which means all of Apple’s parents, including Fruit, can be traced all the way back to Object.

The bottom line is that the compiler supports up conversions, but not down conversions. Specifically, I can assign an Apple object to a Fruit reference, but if I assign a Fruit object to an Apple reference, I have to use a cast.

6. Pay attention

Static methods do not have access to a class’s generics

You can see that the Idea prompt cannot reference a static context.

Type cannot be changed after creation

List<Player> cannot insert any other type. You cannot change a specified type

3. Type judgment problem

Problem: Because the type cannot be retrieved after compilation, it is impossible to determine the type of the class at run time.

We can solve the problem that the type information of generics cannot be determined due to erasure by the following code:

/** * Check the type *@authorParsley *@param <T>
*/
public class GenClass<T{ Class<? > classType;public GenClass(Class
        classType) {
       this.classType = classType;
  }
   public boolean isInstance(Object object){
       returnclassType.isInstance(object); }}Copy the code

Solution: We do this by passing in a concrete class type in the constructor when we create the object, and then using that class object to determine the type.

4,Creating type Instances

Problem: There are two reasons why new T() cannot be found in generic code. Instead, there is no way to determine whether T contains a no-parameter constructor.

In the previous article, there was a requirement to instantiate specific execution nodes based on different node configurations, that is, to create specific IfNodes based on IfNodeCfg.

Public abstract class AbsNodeCfg<T> {public abstract getInstance(); }Copy the code
public class IfNodeCfg extends AbsNodeCfg<IfNode>{
   @Override
   public IfNode getInstance(a) {
       return newIfNode(); }}Copy the code

 


/** * Create instance *@authorParsley * /
public class IfNode {}Copy the code

Solution: Create specific instances for specific types, extend the AbsNodeCfg directly, and implement specific nodes.

7,

Generics create a set of classes and methods. The virtual machine has no concept of objects of generic type. It treats all objects as ordinary objects

If you have any questions, you can leave a message and we can discuss it together. If you have no questions, you can leave a message and we can make friends

Typing is not easy, like, forward, follow sanlian, thank you for your support.