Introduction and use of generics in Java

Introduction and use of generics in Java

! Today, I will mainly tell you about the use of generics in Java and what is generics? Please see the text below

  • Generic overview

We all know that collections (list, map...) in Java can store any object, as long as the objects are stored in the collection, then they will all be promoted to the Object type. When we take out each object and perform the corresponding operation, we must use type conversion. Look at the following sample code

package com.mobaijun;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class GeneriDemo1{
    public static void main(String[] args) {
        Collection coll = new ArrayList();
        coll.add("mobai");
        coll.add("ink white");
        coll.add(5);//Because the collection does not make any restrictions, any type can be stored in it
        Iterator it = coll.iterator();
        while (it.hasNext()) {
           //To print the length of each string, it is necessary to convert the iterated object into String type
            String str = (String) it.next();
            System.out.println(str.length());
        }
    }
}

We can see that the console print result is an exception, and the exception information is as follows:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

A java.lang.ClassCastException occurred during runtime of this demo, and the main class could not be found or the class could not be loaded. Why does a type conversion exception occur? Let's analyze it: because any type of element in the collection can be stored. Causes a ClassCastException at runtime to be forced to be taken out. How to solve this problem?

Although Collection can store various objects, in fact, Collection only stores objects of the same type. For example, they are storing string objects. Therefore, after JDK5, a new generic (Generic) syntax has been added, allowing you to specify classes or methods to support generics when designing the API, so that when we use the API, it becomes more concise and gets the compile time Grammar check.

A one-sentence summary is: Generics can use unknown types in classes or methods in advance.

  • So what are the benefits of using generics?

Look at the following code to experience the benefits of generics:

package com.mobaijun;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class GeneriDemo2 {
    public static void main(String[] args) {
        Collection<String> list = new ArrayList<String>();
        list.add("mobai");
        list.add("ink white");
       //list.add(5);
       //When the collection type is clear, the storage type is inconsistent, and it will compile and report an error        
       //The collection has clarified the specific element type stored, then when using the iterator, the iterator will also know the specific traversal element type
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String str = it.next();
           //When using Iterator<String> to control the element type, there is no need to force it. The obtained element is directly of type String            
            System.out.println(str.length());
        }
    }
}
  • Definition and use of generics

Generics are used to flexibly apply data types to different classes, methods, and interfaces. Pass the data type as a parameter.

Generic definition format:

Modifier class class name <represents generic variable> {}

Sample code:

class ArrayList<E> {
    public boolean add(E e) {
    }
    public E get(int index) {
    }
}

Generics are not specific when they are defined, but become specific when they are used. Determine the specific data type of the generic when using it.

Use generics: when to determine generics.

Determine generics when creating objects

For example, ArrayList<String> list = new ArrayList<String>();

At this point, the value of variable E is of type String, then our type can be understood as

class ArrayList<String> {
    public boolean add(String e) {
    }
    public String get(int index) {
    }
}

For another example, ArrayList<Integer> list = new ArrayList<Integer>();

At this time, the value of the variable E is the Integer type, then our type can be understood as:

class ArrayList<Integer> {
    public boolean add(Integer e) {
    }
    public Integer get(int index) {
    }
}
  • Generic method

Sample code:

public class MyGenericMethod {
    public <MVP> void show(MVP mvp) {
        System.out.println(mvp.getClass());
    }

    public <MVP> MVP show2(MVP mvp) {
        return mvp;
    }
}

When the method is called, clarify the type of the generic: the code is as follows

package com.mobaijun;

public class GeneriDemo3 {
    public static void main(String[] args) {
        MyGenericMethod my = new MyGenericMethod();
        my.show("show");
        my.show(18);
        my.show(178.0);
    }
}
  • Generic interface

Sample code:

package com.mobaijun;

public interface MyGenericInterface<E> {
    public abstract void add(E e);
    public abstract E gitE();
}

Let's take a look at how to use generics if you want to define a class:

Sample code:

package com.mobaijun;

public class MyImpl implements MyGenericInterface<String>{
    @Override
    public void add(String s) {
       //omitted
    }

    @Override
    public String gitE() {
        return null;
    }
}

At the beginning of the class, we defined the generic type, then the value of the generic e at this time is String;

  • If you are always unsure of the type of the generic, you can determine the type of the generic until the object is created
package com.mobaijun;

/**
 * Not sure about the type of generic
 * @param <E>
 */
public class MyImpl2<E> implements MyGenericInterface<E> {

    @Override
    public void add(E e) {

    }

    @Override
    public E gitE() {
        return null;
    }
}
  • Determine the type of generic when creating the object
package com.mobaijun;

/**
 * Determine the type of generic when creating an object
 */
public class GenericInterface {
    public static void main(String[] args) {
        MyImpl2<String> my = new MyImpl2<String>();
        my.add("ink white");
    }
}
  • There is one last knowledge point about generics, which is the wildcard of generics

When a generic class or interface is used, the generic type of the passed data is uncertain and can be represented by the wildcard <?>. But once the generic wildcard is used, only the common methods in the Object class can be used, and the methods of the elements in the collection cannot be used.

The basic usage of wildcards is as follows

Generic wildcard: When you don't know what type to use to receive, you can use?,? to indicate unknown wildcard.

At this time, only data can be accepted, and data cannot be stored in the collection.

Sample code:

package com.mobaijun;

import java.util.ArrayList;
import java.util.Collection;

public class MyDemo {
    public static void main(String[] args) {
        Collection<Integer> c = new ArrayList<Integer>();
       getElement(c);

       Collection<String> c2 = new ArrayList<String>();
       getElement(c2);
    }

   /**
     * The? In the wildcard represents any type of data
     * It should be noted that there is no inheritance relationship between generics,
     * Collection<Object> c2 = new ArrayList<String>(); error example
     * @param collection
     */
    public static void getElement(Collection<?> collection){

    }
}
  • Advanced use of wildcards

When setting the generic type before, it can actually be set arbitrarily, as long as it is a class. But in JAVA's generics, you can specify the upper and lower limits of a generic.

The upper limit of generics:

Format: type name <? extends class> Object name meaning: only this type and its subclasses can be received

The lower limit of generics:

Format: type name <? super class> Object name meaning: only this type and its parent type can be received

For example, such as: now known Object class, String class, Number class, Integer class, where Number is the parent class of Integer

package com.mobaijun;

import java.util.ArrayList;
import java.util.Collection;

public class MyDemo4 {
    public static void main(String[] args) {
        Collection<Integer> c1 = new ArrayList<Integer>();
        Collection<String> c2 = new ArrayList<String>();
        Collection<Number> c3 = new ArrayList<Number>();
        Collection<Object> c4 = new ArrayList<Object>();

        getElementOne(c1);
        getElementOne(c2);//Compile error
        getElementOne(c3);
        getElementOne(c4);//Compile error

        getElementTow(c1);//Compile error
        getElementTow(c2);//Compile error
        getElementTow(c3);
        getElementTow(c4);
    }
   //The upper limit of the generic type: the generic type at this time must be the Number type or a subclass of the Number type
    public static void getElementOne(Collection<? extends Number> collection){}
   //The lower limit of the generic type: at this time the generic type? must be the Number type or the parent type of the Number type
    public static void getElementTow(Collection<? super Number> collection){}
}

The above is the whole content of generics. If it helps you, please click at the end of the article to read it. I wish you a good day, come on!!!