Files
team-learning-program/Java/11.泛型.md
tensorflow-jumao 806de33657 更新
2021-07-10 01:50:21 +08:00

5.3 KiB
Raw Permalink 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 泛型类

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

public class test {

    public static class Point<T> {
        private T var;

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

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

    }

    public static void main(String[] args){
        Point<Float> p = new Point<Float>() ;
        p.setVar(new Float(100.12f)) ;
        System.out.println(p.getVar());
    }

}

括号里面的T是形式类型参数可以随意指定当类被使用的时候就会使用具体的实际类型参数。

需要注意的是,泛型类只能用在成员变量上,并且只能使用引用类型。

11.3 泛型方法

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

  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前
  • 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
  • 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型不能是原始类型像int,double,char的等
public class MethodTest {
	int var = 100;
    String varStr = "Hello Datawhale";
	public <T> T Method(T a) {
		return a;
	}
	public static void main(String[] args) {
		MethodTest t=new MethodTest();
		System.out.println(t.<Integer>Method(t.var));
		System.out.println(t.<String>Method(t.varStr));
	}
 

11.4 泛型接口

class InfoImpl implements Info<String>{   // 定义泛型接口的子类  
    private String var ;                // 定义属性  
    public InfoImpl(String var){        // 通过构造方法设置属性内容  
        this.setVar(var) ;  
    }  
    @Override  
    public void setVar(String var){  
        this.var = var ;  
    }  
    @Override  
    public String getVar(){  
        return this.var ;  
    }  
}  
  
public class GenericsDemo24{  
    public  void main(String arsg[]){  
        InfoImpl i = new InfoImpl("harvic");  
        System.out.println(i.getVar()) ;  
    }  
};  

11.5 类型通配符

类型通配符一般是在不确定具体参数时候,使用?代替。?表示未知类型,类型参数赋予不确定值,只能用在声明类型、方法参数上,不能用在定义泛型类上

public class match {
 
  public static void test(List<?> list) {
 
   List<?> list2; 
   list2 = new ArrayList<String>();
   list2 = new ArrayList<Integer>();
   list2 = new ArrayList<Object>();
 
  }
 
  public static void main(String[] args) {
   test(new ArrayList<String>());
   test(new ArrayList<Integer>());
  }
 
}