泛型

1、泛型方法

调用方法时需要指定泛型的具体类型。

定义泛型方法的规则:

  • 所有的泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前。
  • 每一个类型参数声明部分包含一个或者多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
  • 泛型方法体的声明和其他方法一样。
  • 泛型的类型参数只能代表引用类型,不能是基本类型
public <T> void test(){

}
public <T> String test1(){ return null; }
public <T> T test2(){ return null; } public <T> T test3(T[] t){ return t[0]; } public <T> void test4(T t){ } public <T> T test5(T t){ return t; } public <T,E> void test6(T t, E e){ } public <T,E> T test7(){ return null; } public <T,E> T test8(T t, E e){ return t; } public <T,E,K> T test9(Map<T,E> map){ return null; }

有界参数类型:

有界是指对泛型的参数类型进行限制。

有界类型参数使用extends关键字后面跟边界类型。注意:虽然用的是extends关键字,却不仅限于继承父类E的子类,也可以代指显现了接口E的子类。

多边界泛型:<T extends A & B & C>。注意:A为父类,B、C是接口。

public <T extends Number> void test10(T t){
    byte b = t.byteValue();
}

public <T extends Number& Comparable<T>> Integer test11(T t1,T t2,T t3){
    T max = t1;
    if(t2.compareTo(t1) > 0) {
        max = t2;
    }

    if(t3.compareTo(t1) > 0){
        max = t3;
    }
    return max.intValue();
}

 调用泛型方法

public void testGen(){
    //int[] abc = new int[2];      //参数类型只能是引用类型,不能是基本类型
    Integer[] abc = new Integer[2];
    Integer var1 = test3(abc);

    Integer var2 = test11(1,2,3);
}

泛型静态方法

Java中任何方法,包括静态的和非静态的,均可以用泛型来定义,而且和所在类是否是泛型没有关系。注意,泛型类不允许在静态环境中使用。

下面是泛型方法的定义:[public] [static] <T> 返回值类型 方法名(T 参数列表)

public static <T> T getT(){
    return null;
}

 

2、泛型类

 泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。

和泛型方法一样,泛型类的类型参数声明部分也包含一个或者多个类型参数,参数间用逗号隔开。

一个泛型参数,也被称为一个类型变量,是用于指定一个泛型名称的标识符。

public class TestGenerics<T> {

    private T t;

    private T a;
    private T b;

    public TestGenerics(T a,T b){
        this.a = a;
        this.b = b;
    }

    public void add(T t){
        this.t = t;
    }

    public T getA(){
        return a;
    }

    public T getB(){
        return b;
    }

    public static void main(String[] args) {
        TestGenerics<String> testGenerics = new TestGenerics<>("hello","world");
        String strA = testGenerics.getA();
        String strB = testGenerics.getB();

        TestGenerics<Integer> testGenerics1 = new TestGenerics<>(1,2);
        Integer intA = testGenerics1.getA();
        Integer intB = testGenerics1.getB();
    }

}

通配符

通配符【?】表示一种未知的类型,常用在方法上。

泛型【T】和通配符【?】的区别:

  • 泛型需要在方法返回值前面声明类型参数,通配符不需要
  • Java编译器将泛型推断成具体的类型,把通配符推断成未知类型。java编译器只能操作具体的类型,不能操作未知的类型。
  • 需要操作参数类型使用泛型,查看参数可以使用通配符

无界通配:指的是不限制通配符的界限

上界通配:定义通配符的上界,用关键字extends声明,形如 List<? extends Number>来定义,表示类型只能结束Number类型及其子类

下界通配:定义通配符的下届,用关键字super声明,形如 List<? super Number>来定义,表示类型只能接受Number及其三层父类类型

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

public class TestGenerics2{

    public static void main(String[] args) {

        List<Integer> list1 = new ArrayList<>();
        list1.add(1);

        List<String> list2 = new ArrayList<>();
        list2.add("hello");

        List<Number> list3 = new ArrayList<>();
        list3.add(2);

        getData(list1);
        getData(list2);

        getNum(list1);
       // getNum(list2); //只能是Number类型的及其一下类型

      //  getNum2(list1);  //只能是Number类型及其以上类型
        getNum2(list3);
    }


    /**
     * 泛型方法
     * @param list
     * @param <T>
     */
    public static <T> void setData(List<T> list){
        list.add((T) new Object());
        list.add(null);
    }


    /**
     * 无界通配符
     * @param list
     */
    public static void getData(List<?> list){
        System.out.println(list.get(0));
      //  list.add(new Object());   //无法添加
        list.add(null);
    }

    /**
     * 上界通配符
     * @param list
     */
    public static void getNum(List<? extends Number> list){
        System.out.println(list.get(0));
    }

    /**
     * 下届通配符
     * @param list
     */
    public static void getNum2(List<? super Number> list){
        System.out.println(list.get(0));
    }

}

 

3、泛型接口

泛型接口的声明和非泛型接口的声明类似,除了在接口名后面添加了类型参数声明部分。

通过类去实现泛型接口时,需要指定泛型参数T的类型

public interface IGenerics3<T> {
    int f = 10;  //默认是 static final

    T next(T t); //默认是 public
}

实现类

public class Generics3Impl implements IGenerics3<Integer>{

    @Override
    public Integer next(Integer integer) {
        return null;
    }
}


public class Generics3Impl implements IGenerics3<String>{

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

 

posted @ 2020-10-28 14:45  jernia  阅读(133)  评论(0编辑  收藏  举报