Java 泛型

Java 泛型

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

  • 适用于多种数据类型执行相同的代码
  • 泛型中的类型在使用时指定
  • 泛型归根到底就是“模版”

优点:使用泛型时,在实际使用之前类型就已经确定了,不需要强制类型转换。

泛型主要使用在集合中。

泛型的使用

泛型有三种常用的使用方式:泛型类泛型接口泛型方法

泛型类

一个泛型类(generic class)就是具有一个或多个类型变量的类。

语法:

class 类名称 <泛型标识:可以随便写任意标识号,标识指定的泛型的类型>{
  private 泛型标识 /*(成员变量类型)*/ var; 
  .....

  }
}

例子:

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class GenericTest<T> {
    //value这个成员变量的类型为T,T的类型由外部指定
    private T value;

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

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

    public void setValue(T value) {
        this.value = value;
    }
}

注意:

  • 泛型的类型参数只能是类类型,不能是简单类型。
  • 传入的实参类型需与泛型的类型参数类型相同。
  • 在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。
  • 不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。
if(ex_num instanceof Generic<Number>){ }

泛型接口

泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生成器中,生成器相当于对象工厂,是一种专门用来创建对象的类。

例子:

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

继承接口:

当实现泛型接口的类,传入泛型实参时:

public class FruitGenerator implements Generator<String> {

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

}

当实现泛型接口的类,未传入泛型实参时:

public class FruitGenerator<T> implements Generator<T> {

    private T next;

    public FruitGenerator(T next) {
        this.next = next;
    }

    @Override
    public T next() {
        return next;
    }

    public static void main(String[] args){
        FruitGenerator<String> fruit = new FruitGenerator<>("Fruit");
        System.out.println(fruit.next);
    }

}

泛型方法

可以使用泛型来表示方法。

例子:

 public <T> void say(T x){
        System.out.println(x.getClass().getName());
    }

泛型方法能使方法独立于类而产生变化,以下是一个基本的指导原则:

无论何时,如果你能做到,你就该尽量使用泛型方法。也就是说,如果使用泛型方法将整个类泛型化,那么就应该使用泛型方法。另外对于一个static的方法而已,无法访问泛型类型的参数。所以如果static方法要使用泛型能力,就必须使其成为泛型方法。

泛型通配符

类型通配符一般是使用?代替具体的类型实参,注意了,此处’ ?’是类型实参,而不是类型形参

可以解决当具体类型不确定的时候,这个通配符就是 ? ;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。

例子:

public static void generic(List<?> list){
	for (Object o : list) {
            
    }
}

上界通配符:<? extends ClassType>该通配符为 ClassType的所有子类型。它表示的是任何类型都是ClassType类型的子类。

例子:

public static void generic(List<? extends String > list){
	for (Object o : list) {
            
    }
}

下界通配符:<? super ClassType>该通配符为 ClassType的所有超类型。它表示的是任何类型的父类都是 ClassType。

例子:

public static void generic(List<? super String > list){
	for (Object o : list) {
            
    }
}
posted @ 2021-02-24 19:57  拒绝平庸*  阅读(53)  评论(0编辑  收藏  举报