Files
team-learning-program/Java/11.泛型.md
tensorflow-jumao 4bf855c36d 第一次提交
2021-07-07 23:51:30 +08:00

5.1 KiB
Raw Blame History

11.泛型

11.1 什么是泛型

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

首先来看一个例子

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

public class test {

    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("string");
        list.add(100);

        for (int i = 0; i < list.size(); i++) {
            String name = (String) list.get(i); // 1
            System.out.println("name:" + name);
        }
    }
}

上述代码会出现 Exception in thread "main" java.lang.ClassCastException 错误

ArrayList由String类型和Integer类型而两者都以String格式使用所以出现了上述错误。

这个时候就用得上泛型了

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

public class test {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();
        list.add("string");
        list.add(100);   

        for (int i = 0; i < list.size(); i++) {
            String name = list.get(i); // 2
            System.out.println("name:" + name);
        }
    }
}

上述代码会编译错误如果使用idea的话会出现下述错误提示

java: 对于add(int), 找不到合适的方法
    方法 java.util.Collection.add(java.lang.String)不适用
      (参数不匹配; int无法转换为java.lang.String)
    方法 java.util.List.add(java.lang.String)不适用
      (参数不匹配; int无法转换为java.lang.String)

这里通过List<String>限定了集合内的元素只能是String类型。

泛型使得代码可以被不同类型的对象重用

11.2 泛型方法

下面是定义泛型方法的规则:

  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前
  • 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
  • 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型不能是原始类型像int,double,char的等
/**
 * 泛型方法的基本介绍
 * @param tClass 传入的泛型实参
 * @return T 返回值为T类型
 * 说明:
 *     1public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
 *     2只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
 *     3<T>表明该方法将使用泛型类型T此时才可以在方法中使用泛型类型T。
 *     4与泛型类的定义一样此处T可以随便写为任意标识常见的如T、E、K、V等形式的参数常用于表示泛型。
 */
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
  IllegalAccessException{
        T instance = tClass.newInstance();
        return instance;
}

11.3 泛型类

一个泛型类就是拥有一个或者多个类型变量的类。下面看一个简单例子:

ublic class Generic<T>{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
    private T key;

    public Generic(T key) { //泛型构造方法形参key的类型也为TT的类型由外部指定
        this.key = key;
    }

    public T getKey(){ //泛型方法getKey的返回值类型为TT的类型由外部指定
        return key;
    }
}

11.4 泛型接口

//定义一个泛型接口
public interface Generator<T> {
    public T next();
}

11.5 类型通配符

类型通配符一般是使用?代替具体的类型参数。例如 List 在逻辑上是List,List 等所有List<具体类型实参>的父类。

import java.util.*;
 
public class GenericTest {
     
    public static void main(String[] args) {
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        
        name.add("icon");
        age.add(18);
        number.add(314);
 
        getData(name);
        getData(age);
        getData(number);
       
   }
 
   public static void getData(List<?> data) {
      System.out.println("data :" + data.get(0));
   }
}