什么是泛型

224 阅读2分钟

这是我参与8月更文挑战的第1天,活动详情查看:[8月更文挑战] (juejin.cn/post/698796… "juejin.cn/post/698796…")

前言

Java泛型设计原则:只要在编译时期没有出现警告,那么运行时期就不会出现ClassCastException异常.

一些强类型程序语言支持泛型,其主要目的是加强类型安全及减少类转换的次数,但一些支持泛型的程序语言只能达到部分目的。

泛型可以定义在那里

  1. 泛型定义在类上

  2. 泛型定义在方法上

  3. 泛型定义在接口上

1. 泛型类
public class Test<T> {
    private T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }
}

泛型的好处就是用户想要用什么类型,就在创建的时候指定类型,这样使用的时候类会自动转换成你想用的类型,比如你的List定义泛型为String,那么你的get(0)就会获得数组的对象,但类型只会是 String类型,也就是你定义的List泛型的类型

2. 泛型方法
    public <T> void test(T t) {
        System.out.println(t);

    }

注意:什么是泛型方法,决定他的不是传入的参数是否是泛型,而是看这个方法的返回值是否是泛型。

3. 泛型接口

public interface Test<T> {
    T test();
}

它的实现类的类型也必须为传入的指定参数,不然在编译时就报错,这也正是泛型规避开了之后的运行时期会出现ClassCastException异常

以下是错误例子
public class Test2 implements Test<String> {


    @Override
    public Integer test() {
        return null;
    }
}

正确写法
public class Test2 implements Test<String> {


    @Override
    public String test() {
        return null;
    }
}
注意
泛型是不可以使用在全局变量前的

public interface Test<T> {

   /*public abstract 编译时自动添加*/
    T test();
    
    /*public static final 编译时自动添加,因为这是一个接口变量*/
    //不可以添加在这个变量上
    String test = "test";
}

总结: 泛型的使用可以让我们的代码更加具有通用性,不会导致定义一种类型后其他的类型都无法使用该代码

定义泛型的命名

<> 自定义泛型类,尽量使用大写字母

常用的一般为 T,K,V

T 为 Type

K 为 key

V 为value

符合常规命名即可,最好见其名知其意,当然你写个Test 这样的命名也是可以的

泛型的限定符 extends

extends 可以缩小泛型的范围

比如 有三个类 A B C ,A>B>C (这里的大于指的是继承关系)

1. T 继承 A时,泛型范围被缩小到ABC三个
public interface Test<T extends A> {
    Test test();
}

2. T 继承 B时,泛型范围被缩小到BC三个,当你在此使用A是会报错,同理继承C也是一样,会缩小T的范围
public interface Test<T extends B> {
    Test test();
}

总结:1. 还有Java的PECS原则没讲,放到下一期内容 2. 泛型可以在编译时就避免运行时报错 3. 泛型的出现使得程序员对程序更加规范 4. 泛型可以让我们更加直观知道不确定的集合最后生成的实体类是什么类型