Generic

Preface

Prepare for the job hopping interview , Today we begin to enter Java Basic review . I hope students with poor foundation will finish reading this article , Be able to master generics , And the students with good foundation should have the right to review , I hope that after reading this article, you can have a little green memory .

One 、 What is generics

Generic , namely “ Parameterized types ”. When it comes to parameters , The most familiar thing is to define methods with formal parameters , Then we call the method to pass the arguments . So how to understand parameterized types ?

seeing the name of a thing one thinks of its function , That is to parameterize the type from the original concrete type ( Verb ), Similar to variable parameters in methods , In this case, the type is also defined as a parameter ( It can be called type parameter ),

And then use / Specific types are passed in when called ( Type arguments ).

The essence of generics is to parameterize types ( Without creating a new type , Through the different types specified by generics to control the type of formal parameter specific restrictions ). In other words, in the process of using generics .

The data type of the operation is specified as a parameter , This parameter type can be used in a class 、 Interface and method , They are called generic classes 、 Generic interface 、 Generic methods .

Reference resources :https://www.cnblogs.com/coprince/p/8603492.html

1.1 Common generic type variables :

E: Elements (Element), be chiefly used in java Collections framework
K: keyword (Key)
N: Numbers (Number)
T: type (Type)
V: value (Value)

Two 、 Why use generics

Before answering this question , First, two chestnuts , I want to print the string to the console , The following code :

package com.nasus.generic;

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

/**
 * Project Name:review_java <br/>
 * Package Name:com.nasus.generic <br/>
 * Date:2019/12/28 20:58 <br/>
 *
 * @author <a href="turodog@foxmail.com">chenzy</a><br/>
 */
public class Show {

    public static void main(String[] args) {
        List list=new ArrayList();
        list.add(" A good loser ");
        list.add("java  The engineer ");
        list.add(666);
        for (int i = 0; i < list.size(); i++) {
            String value= (String) list.get(i);
            System.out.println(value);
        }
    }
}

My own list It's about loading String To print , But you don't find ? I introduce int When it's type ( Compile time ),Java There is no reminder ( At best IDEA Warning ). Until I loop ( The run-time ) Printing method , Print int When it's type ,Java It's a mistake :

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
 A good loser 
	at com.nasus.generic.Show.main(Show.java:23)
java  The engineer 

Second, chestnuts , I want to implement an addition that can operate all kinds of operations , The following code :

package com.nasus.generic.why;

/**
 * Project Name:review_java <br/>
 * Package Name:com.nasus.generic <br/>
 * Date:2019/12/28 21:18 <br/>
 *
 * @author <a href="turodog@foxmail.com">chenzy</a><br/>
 */
public class Add {

    private static int add(int a, int b) {
        System.out.println(a + "+" + b + "=" + (a + b));
        return a + b;
    }

    private static float add(float a, float b) {
        System.out.println(a + "+" + b + "=" + (a + b));
        return a + b;
    }

    private static double add(double a, double b) {
        System.out.println(a + "+" + b + "=" + (a + b));
        return a + b;
    }

    //  A generic method 
    private static <T extends Number> double add(T a, T b) {
        System.out.println(a + "+" + b + "=" + (a.doubleValue() + b.doubleValue()));
        return a.doubleValue() + b.doubleValue();
    }

    public static void main(String[] args) {
        Add.add(1, 2);
        Add.add(1f, 2f);
        Add.add(1d, 2d);
        System.out.println("--------------------------");
        //  The following three are all calls to generic methods 
        Add.add(Integer.valueOf(1), Integer.valueOf(2));
        Add.add(Float.valueOf(1), Float.valueOf(2));
        Add.add(Double.valueOf(1), Double.valueOf(2));
    }
}

This addition can operate int、float、double type , But the corresponding addition must also be rewritten , At this point, I can actually use a generic method to implement the functions of the above three overloaded methods .

1+2=3
1.0+2.0=3.0
1.0+2.0=3.0
--------------------------
1+2=3.0
1.0+2.0=3.0
1.0+2.0=3.0

So there are three reasons to use generics :

  • Improve readability
  • send ClassCastException This error is detected at compile time
  • It is suitable for multiple data types to execute the same code ( Code reuse )

Reference resources :https://www.jianshu.com/p/986f732ed2f1

3、 ... and 、 A generic,

3.1 Generic classes

Let's specify the type we want to pass into the generic class , Define generics on classes , When users use this class , To make the type clear , such as : Define a universal entity data temporary storage tool class .

Be careful : The generic class determines the type when it is initialized

package com.nasus.generic.how;

/**
 * Project Name:review_java <br/>
 * Package Name:com.nasus.generic.how <br/>
 * Date:2019/12/28 21:35 <br/>
 *
 * @author <a href="turodog@foxmail.com">chenzy</a><br/>
 */
public class EntityTool<T> {

    private T entity;

    public T getEntity() {
        return entity;
    }

    public void setEntity(T entity) {
        this.entity = entity;
    }

    public static void main(String[] args) {
        //  Create an object and specify the element type 
        EntityTool<String> stringTool = new EntityTool<>();
        stringTool.setEntity(" A good loser ");
        String s = stringTool.getEntity();
        System.out.println(s);


        //  Create an object and specify the element type 
        EntityTool<Integer> integerTool = new EntityTool<>();
        //  here , If it's still here  String  type , It will report an error at compile time 
        integerTool.setEntity(10);
        int i = integerTool.getEntity();
        System.out.println(i);
    }
}

3.2 Generic methods

Sometimes we just want to use generics in methods , It can be defined as :

It is worth noting that :

  • Unlike generic classes , Generic methods determine the final type only when they are called
  • If there is a return value , The return value does not need to be forced
package com.nasus.generic.how;

/**
 * Project Name:review_java <br/>
 * Package Name:com.nasus.generic.how <br/>
 * Date:2019/12/28 21:46 <br/>
 *
 * @author <a href="turodog@foxmail.com">chenzy</a><br/>
 */
public class Show {

    public static  <T> T show(T t) {
        System.out.println(t);
        return t;
    }

    public static void main(String[] args) {
        //  The return value does not need to be forced , What's going in there , Return is what 
        String s = show(" A good loser ");
        int num1 = show(666);
        double num2 = show(666.666);
        System.out.println("------------------------");
        System.out.println(s);
        System.out.println(num1);
        System.out.println(num2);
    }
}

3.3 Generic interface

There are two ways to implement generic interfaces :

One is to implement the type parameter variable of class ambiguous generic interface , In this case, the implementation class must also define type parameter variables ( For example, below Showimpl

Interface :

public interface Show<T> {
    void show(T t);
}
public class ShowImpl<T> implements Show<T>{

    @Override
    public void show(T t) {
        System.out.println(t);
    }

    public static void main(String[] args) {
        ShowImpl<String> stringShow = new ShowImpl<>();
        stringShow.show(" A good loser ");
    }
}

The second is to define the type parameter variables of generic interfaces

public class ShowImpl2 implements Show<String>{

    @Override
    public void show(String s) {
        System.out.println(" A good loser ");
    }
}

3.5 Restrict generic type variables

Limit the upper limit of generic types

In fact, it is equivalent to specifying the parent class of a generic class
Declaration class : Class name < Generic identity extends class >{}

Use... In classes :

//  Used on classes 
public class Show<T extends Number> {

    private T show(T t){
        System.out.println(t);
        return t;
    }

    public static void main(String[] args) {
        //  Specify the type when initializing 
        Show<Integer> show = new Show<>();
        show.show(6666666);

        //  Report errors , This class only accepts inheritance from  Number  Generic parameters for 
        // Show<String> stringShow = new Show<>();
    }
}

Method used in :

Define the object : Class name < Generic identity extends class > Object name

public class Info<T> {

    //  Define generic variables 
    private T var;

    public void setVar(T var) {
        this.var = var;
    }

    public T getVar() {
        return this.var;
    }

    public String toString() {
        return this.var.toString();
    }
}
public class ShowInfo {

    //  Used in methods , receive calls only  Number  And its subclasses 
    public static void showInfo(Info<? extends Number> t) {
        System.out.print(t);
    }

    public static void main(String args[]) {
        Info<Integer> i1 = new Info<>();
        Info<Float> i2 = new Info<>();
        i1.setVar(666666666);
        i2.setVar(666666.66f);
        showInfo(i1);
        showInfo(i2);
    }

}

Limit the lower bound of a generic type

Define the object : Class name < Generic identity extends class > Object name

Contrary to the specified upper limit , It's easy to specify the lower limit , It is equivalent to specifying a subclass of a generic class , I won't repeat .

public class ShowInfo {

    //  We only accept  String  Parent class of 
    public static void showInfo(Info<? super String> t) {
        System.out.println(t);
    }

    public static void main(String args[]) {
        Info<String> stringInfo = new Info<>();
        Info<Object> objectInfo = new Info<>();
        stringInfo.setVar(" A good loser ");
        objectInfo.setVar(new Object());
        showInfo(stringInfo);
        showInfo(objectInfo);
    }

}

3.6 Wildcard type

  • <? extends Parent> Specifies the upper limit of the generic type
  • <? super Child> Specifies the next generation of generic types
  • <?> Specified an unrestricted generic type

3.7 Generic erase

Generics are provided to javac Used by the compiler , It is used to define the input type of the collection , Let the compiler at the source level , That is to insert illegal data into the collection . But the compiler compiles java After procedure , Generated class The file will no longer have the generics information , So that the efficiency of the program is not affected , This process is called “ erase ”.

3.8 Specification for using generics

1、 Cannot instantiate generic class
2、 Static variables or methods cannot reference generic type variables , But static generic methods are OK
3、 A base type cannot be a generic type
4、 Can't use instanceof Keywords or == Determine the type of a generic class
5、 The native type of a generic class has nothing to do with the generic passed , No matter what type of delivery , Native classes are the same
6、 A generic array can be declared but cannot be instantiated
7、 Generic classes cannot inherit Exception perhaps Throwable
8、 You can't catch a generic type qualified exception, but you can throw a generic type qualified exception

Four 、 Source code address

  • github Source code address :https://github.com/turoDog/review_java

If you see this , Like this article , Help " forward " Or order " Looking at ", Would you? ? I wish you all the best 2020 A rich man . WeChat search 「 A good loser 」, Welcome to your attention .

reply 「1024」 Send you a complete set java、python、c++、go、 front end 、linux、 Algorithm 、 big data 、 Artificial intelligence 、 Small program and English Course .

reply 「 e-book 」 Send you 50+ Ben java e-book .

 Most comprehensive tutorial

 A good loser