Read this article carefully to make sure you have a new understanding of generics, if not, please follow the line to hit me.

An overview of the

Quote baidu Baike’s answer

Generics are a feature of programming languages. Allows programmers writing code in strongly typed programming languages to define variable parts that must be specified before use. Support for generics varies from programming language to programming language and from compiler to runtime environment. A data type parameterized for code reuse to improve software development efficiency. Generic classes are reference types and heap objects, mainly introducing the concept of type parameters.

Generics are about putting off specifying specific types until you create objects or call methods.

Parameterized types, which are passed as arguments, Object< datatypes >, which can only be reference types, not primitive types.

Such as:

Object<Integer>  //true
Object<int> //false
Copy the code

Why can’t data types in generics be primitive types?

Since the virtual machine will convert generics to Object during compilation, and primitive types are not Object types, the data types in generics cannot be primitive types.

Why use generics?

The benefit of the introduction of generics into the Java language is security and simplicity. The benefit of generics is that type safety is checked at compile time, and all casts are automatic and implicit, increasing code reuse.

It is important to eliminate casts to reduce the chance of errors, for example:

public class Test {
    public static void main(String[] args){
        List list = new ArrayList();
        list.add("1"); 
        list.add(1);
        int i = (int)list.get(0); // java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
        int j = (int)list.get(1); }}Copy the code

The above code has no problem at compile time, because the add method of list is of Object type, so there is no problem at compile time. However, when we call the list at run time, we do not know what type of parameters are stored in the list, so it may report type conversion error when fetching.

This error would not have occurred if generics had been used.

public class Test {
    public static void main(String[] args){
        List<String> list = new ArrayList();
        list.add("1");
        list.add(1);// Error at compile time, because generics are used, the virtual machine will check for generic type safety at compile time.}}Copy the code

Generics only exist at compile time.

Let me give you an example.

public class Test {
    public static void main(String[] args) throws Exception{
        List<String> list = new ArrayList();
        list.add("hello");
        //list.add(23) // Compile time error
        Class c = Class.forName("java.util.ArrayList");
        Method m = c.getMethod("add",Object.class);
        m.invoke(list,23);
        System.out.println(list); // [hello, 23]}}Copy the code

As you can see from the above, generics only work at compile time. Why not at run time? This is because the concept of generic erasure, in plain English, means that information about generics does not go through run time.

The use of generics

Generics are useful in three ways

Generic classes: public class Test

}{} T indicates an unknown type

Generic interface: Public interface Test

{} same as defining a class

Public

void Test(T name){}

Use of generic classes

A generic class has a very important position in Java, which we use most is the ArrayList, HashMap, HashSet.

Since it is to take you to understand Java generics, certainly not the source code of those container classes ah, those container classes have been very perfect if you want to take you to see, will certainly see more dizzy, so we define a generic class.

// This T can be substituted for any letter, except that I use the same T for generics. You can substitute A,B, C...
public class Test<T> {
    T name;
    public Test(T name){
        this.name = name;
    }
    public T getName(a) {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }

Copy the code
// If you do not pass generic types, then the default is Object
Test test = new Test("hello");
// The data type passed in should not be a basic type, otherwise an error will be reported at compile time
Test<Integer> test1 = new Test<>(418);
Copy the code

Use of generic interfaces

Generic interfaces are defined in much the same way that generic classes are defined, so the generic interfaces that we see are List,Map,Set.

First, as always, we define a generic interface ourselves.

public interface Test<T>{
    T getName(T name);
}
Copy the code
// If the interface does not pass in the data type, you need to write the generic declaration to the class or it will report an error
class Test1<T> implements Test<T>{

    @Override
    public T getName(T name) {
        return null; }}// When an interface is passed a data type, there is no need to write the generic declaration to the class
class Test2 implements  Test<String>{

    @Override
    public String getName(String name) {
        returnname; }}Copy the code

The use of generic methods

The use of generic methods

public <T> void getName(T name){} 
public <T,K> void getNameAndValue(T name, K value){}
public <T,K,V> void getNameAndValueAndV(T name, K value, V v){}// How many generics are required for the parameter, and how many generics must be defined before the return value is returned otherwise there will be errors at compile time
Copy the code

Generic wildcard

Why use wildcards?

There is an inheritance relationship between classes in Java. For example, Cat extends Animals is a subclass of Animal. Collections do not inherit. List

catList and List

animalList you can’t say that animalList is a parent of catList, so it’s hard to see the connection between these two classes, But what if we want to add only subclasses of Animals to the list?

  1. One way is to define a list as many subclasses as Animals have. This method can be implemented, but Animals have a hundred, a thousand, or ten thousand subclasses.

  2. The second way is to use wildcards. Such as: the List
    Animals At this point Animals can only add subclasses of Animals to a list.

The basic concept of wildcards?

  1. Unbounded wildcards:? For example, generics can accept all unknown types

    public class Test {
       public static void main(String []args){
           List<Integer> list = new ArrayList<>();
           list.add(1);
           list.add(2);
           list.add(3);
           list.add(4);
           List<String> stringList = new ArrayList<>();
           stringList.add("h");
           stringList.add("e");
           stringList.add("l");
           stringList.add("l");
           stringList.add("o");
           getList(stringList);
           getList(list);
       }
        // Whatever List is passed will be received
       public static List getList(List
              list){
           return list;
       }
    Copy the code

    Use the List <? > declare a List that cannot use add because you don’t know what type it is, but list.add(null) can because null is available for all types. For example

    public static List getList(List
              list){
        // list.add(1); // The error will be reported at compile time
        // list.add("hello"); // The error will be reported at compile time
           list.add(null);// Added successfully
           return list;
    }
    Copy the code

    You can only receive objects with get because you don’t know what your type is.

    public static List getList(List
              list){
        int i = list.get(0); // Compile time error
        String j = list.get(1); // Compile time error
        Object o = list.get(3); // Run correctly
        return list;
    }
    Copy the code
  2. Upper boundary wildcard number: <? Extends E> accepts generics of E and subtypes of E. In this case, E is not only a class, but also an interface.

    // This inherits the usage of the class
    public class Test {
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            list.add(1);
            getList(list);
            List<String> strings = new ArrayList<>();
            strings.add("hello");
            getList(strings);// Compile time error
        }
    
        public static List getList(List<? extends Number> list) {
            returnlist; }}Copy the code
    public class Test {
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            list.add(1);
            getList(list);// Compile time error
            List<Test2> test2s = new ArrayList<>();
            getList(test2s);
        }
        // The upper boundary is the implementation of the interface. Any class that implements this interface can be passed in as a generic
        public static List getList(List<? extends Test1> list) {
            returnlist; }}interface Test1{}class Test2 implements Test1{}
    Copy the code

    The upper boundary <? Extends E> means that the type you pass in must be a subclass of E, or a class that implements the interface.

  3. Bottom wildcard number: <? Super E> means that the type passed in has to be E and the parent of E, for example

    public class Test { public static void main(String[] args) { List<Animals> animals = new ArrayList<>(); getList(animals); List<Cat> cats = new ArrayList<>(); getList(cats); List<Dog> dogs = new ArrayList<>(); getList(dogs); } public static List getList(List<? super Cat> list) {return list;
        }
    }
    class Animals{}
    class Cat extends  Animals{}
    class Dog extends  Animals{}
    Copy the code

The End

I think we use most in Java generics is List, Map the two, in fact, our programming use generics, more can reduce the amount of code, still can make the code look better, with lei jun says a word, the other people all say me to write the code, like poem, hope you can in the Java road more walk far.

Finally, if you like this article, please forward your little hands and then go, each of your forwarding points and praises is the power of my writing.

Pay close attention to qianjue (JUE) public number, the backstage message communicates to me together.