【Java基础】- 泛型

1.什么是泛型

JAVA 1.5的重大改变就是泛型的引入,实现了参数化类型的概念,使代码适用于多种类型,是通过解耦类、方法与所使用类型之间的约束。
使得类型范围在接口的实现和类的集成之上。

2.泛型类

泛型类就是将泛型定义在类上,使用类时才会确定类型,类中的属性、方法也可以使用泛型

2.1泛型类的定义

public class GenericityClass<T> {
    //属性和方法可以直接使用泛型
    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
注意:类上声明泛型只对非静态成员、非静态方法有效 泛型类中的静态方法不能直接使用类的泛型,可以声明为静态泛型方法再使用
    //编译报错
    public static void getT(T t){
    }

    //编译正常
    public static <T>  void getT(T t){
    }
    
泛型的类型未确定时,只能调对象与类型无关的方法,不能调用对象与类型有关的方法。 例如集合的add()方法
    public static void main(String[] args) {
        List<? extends Number> testList = new ArrayList<>();
        testList.get(0);
        testList.add(1);//error
    }

2.2泛型的使用

使用时声明类型,类中的方法、属性都会为该类型。

public static void main(String[] args) {
    GenericityClass<Integer> genericityClass = new GenericityClass<>();
    genericityClass.setData(10);
    System.out.println(genericityClass.getData());
}

3.泛型方法

有时不需要将整个类定义为泛型,只需要将方法定义为泛型即可。

3.1 泛型方法的定义

public class GenericityFunc {

    public <T> void print(T t){
        System.out.println(t.toString());
    }
}

3.2 泛型方法的使用

public static void main(String[] args) {     
    GenericityFunc genericityFunc = new GenericityFunc();
    genericityFunc.print("hello genericity function ");
    genericityFunc.print(10);
    genericityFunc.print(new int[]{1,2,3,4,5,6});
}

4.泛型的继承

只要是Java类就可以存在继承关系,泛型的继承可以

  • 1.明确泛型类
  • 2.不明确泛型类
//泛型父类
public abstract  class FooClass<T> {
   public abstract T getT();
}
//子类不明确类型
public class SonClass<T>  extends FooClass<T>{

    private T t;

    @Override
    public T getT() {
        return t;
    }
}
//子类指定类型
public class SonClass2 extends FooClass<String>{

    private String data = "this is SonClass2";

    @Override
    public String getT() {
        return data;
    }
}

5.类型通配符

T,E,K,V,?的区别
本质上这些个都是通配符,没啥区别,只不过是编码时的一种约定俗成的东西。比如上述代码中的 T ,我们可以换成 A-Z 之间的任何一个 字母都可以,并不会影响程序的正常运行,但是如果换成其他的字母代替T,在可读性上可能会弱一些。通常情况下,T,E,K,V,?是这样约定的:

  • ?表示不确定的 java 类型
  • T (type) 表示具体的一个java类型
  • K V (key value) 分别代表java键值中的Key Value
  • E (element) 代表Element

通配符 "?",通常是在变量赋值或变量声明时用的,?通配符来表示任意类型。
用在声明泛型类或泛型方法会报错 即不能用于定义泛型

List<?> unknownList;
List<? extends Number> unknownNumberList;   //上界
List<? super Integer> unknownBaseLineIntgerList; //下界

当使用通配符作为形参时,只有变量明确定义了类型且不符合方法的声明才会编译异常

    public static void main(String[] args) {
        List commonList = new ArrayList();
        List<? extends Integer> integerList = new ArrayList<>();
        List<String> stringsList = new ArrayList();
        print(commonList); //编译通过
        print(integerList);//编译通过
        print(stringsList);//编译错误


    }
    public static  void print(List<? extends Number> list){
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
    }

6.泛型的擦除

泛型是 Java 1.5 版本才引进的概念,在这之前是没有泛型的概念的,但显然,泛型代码能够很好地和之前版本的代码很好地兼容。因为,泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。

在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如<T>则会被转译成普通的 Object 类型,如果指定了上限如 则类型参数就被替换成类型上限String

不能创建泛型数组的原因:数组中存储的类型是确定的,泛型在运行时,被擦除

7.泛型的应用

1.通用Service使用泛型类,实际实现时类指定业务pojo.

public interface BasicService<T extends BaseEntity,M extends BaseMapper<T>> {

    T getModelById(Long id);

    List<T> getListByEqualsMap(Map<String,Object> mapEquals);

    T getModelByEqualsMap(Map<String,Object> mapEquals);

    List<T> selectBySelective(T t);

    int insertModel(T t,String userName);

    int insertSelective(T t,String userName);

    int updateById(T t,Long id,String userName);
}
posted @ 2020-08-18 19:53  ShinyRou  阅读(249)  评论(1编辑  收藏  举报