Java泛型

我是南城余!阿里云开发者平台专家博士证书获得者!

欢迎关注我的博客!一同成长!

一名从事运维开发的worker,记录分享学习。

专注于AI,运维开发,windows Linux 系统领域的分享!

本章节对应知识库泛型 (yuque.com)icon-default.png?t=N7T8https://www.yuque.com/nanchengcyu/java/rfng0hcks3gqaork


 

Java中的泛型,就类似于上述场景中的标签。

Java泛型_第1张图片

泛型

在集合中使用泛型之前可能存在的问题

》类型不安全。因为add()的参数是Object类型,意味着任何类型的对象都可以添加成功

》需要强转操作,繁琐。还可能导致ClassCastException

自定义泛型类、接口、方法

class Order{}

》public 返回值类型 方法名(形参列表){}(在返回值类型前面才能判断其为泛型)

泛型,是程序中出现的不确定的类型

以集合为例,把一个集合中的内容限制在一个特定的数据类型中

使用说明

泛型使用在

集合:ArrayList、HashMap、Iterator

比较器:Comparable、Comparator

》集合框架在声明接口和其实现类时,使用了泛型(jdk5.0),在实例化集合对象时

如果没有泛型,则认为操作的默认为Object类型的数据

如果使用了泛型,则需要指明泛型的具体操作类型。一旦指明了泛型的具体类型,则在集合的相关方法中,只能添加此类型

//泛型在List中的使用
@Test
public void test1(){
    //举例:将学生成绩保存在ArrayList中
    //标准写法:
    //ArrayList list = new ArrayList();
    //jdk7的新特性:类型推断
    ArrayList list = new ArrayList<>();

    list.add(56); //自动装箱
    list.add(76);
    list.add(88);
    list.add(89);
    //当添加非Integer类型数据时,编译不通过
    //list.add("Tom");//编译报错

    Iterator iterator = list.iterator();
    while(iterator.hasNext()){
        //不需要强转,直接可以获取添加时的元素的数据类型
        Integer score = iterator.next();
        System.out.println(score);
    }
}
在哪里可以声明类型变量
  • 声明类或接口时,在类名或接口名后面声明泛型类型,我们把这样的类或接口称为泛型类或泛型接口。
【修饰符】 class 类名<类型变量列表> 【extends 父类】 【implements 接口们】{
    
}
【修饰符】 interface 接口名<类型变量列表> 【implements 接口们】{
    
}

//例如:
public class ArrayList    
public interface Map{
    ....
}
  • 声明方法时,在【修饰符】与返回值类型之间声明类型变量,我们把声明了类型变量的方法,称为泛型方法。
[修饰符] <类型变量列表> 返回值类型 方法名([形参列表])[throws 异常列表]{
    //...
}

//例如:java.util.Arrays类中的
public static  List asList(T... a){
    ....
}
说明

① 我们在声明完自定义泛型类以后,可以在类的内部(比如:属性、方法、构造器中)使用类的泛型。

② 我们在创建自定义泛型类的对象时,可以指明泛型参数类型。一旦指明,内部凡是使用类的泛型参数的位置,都具体化为指定的类的泛型类型。

③ 如果在创建自定义泛型类的对象时,没有指明泛型参数类型,那么泛型将被擦除,泛型对应的类型均按照Object处理,但不等价于Object。

  • 经验:泛型要使用一路都用。要不用,一路都不要用。

④ 泛型的指定中必须使用引用数据类型。不能使用基本数据类型,此时只能使用包装类替换。

⑤ 除创建泛型类对象外,子类继承泛型类时、实现类实现泛型接口时,也可以确定泛型结构中的泛型参数。

如果我们在给泛型类提供子类时,子类也不确定泛型的类型,则可以继续使用泛型参数。

我们还可以在现有的父类的泛型参数的基础上,新增泛型参数。

注意

① 泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如:

② JDK7.0 开始,泛型的简化操作:ArrayList flist = new ArrayList<>();

③ 如果泛型结构是一个接口或抽象类,则不可创建泛型类的对象。

④ 不能使用new E[]。但是可以:E[] elements = (E[])new Object[capacity];

参考:ArrayList源码中声明:Object[] elementData,而非泛型参数类型数组。

⑤ 在类/接口上声明的泛型,在本类或本接口中即代表某种类型,但不可以在静态方法中使用类的泛型。

⑥ 异常类不能是带泛型的。

class Person {
    // 使用T类型定义变量
    private T info;
    // 使用T类型定义一般方法
    public T getInfo() {
        return info;
    }
    public void setInfo(T info) {
        this.info = info;
    }
    // 使用T类型定义构造器
    public Person() {
    }
    public Person(T info) {
        this.info = info;
    }
    // static的方法中不能声明泛型
    //public static void show(T t) {
    //
    //}
    // 不能在try-catch中使用泛型定义
    //public void test() {
        //try {
        //
        //} catch (MyException ex) {
        //
        //}
    //}
}
泛型在继承上的体现

① 类SuperA是类A的父类,则G与G的关系,G和G是并列的两个类,没有任何子类关系

比如:ArrayList、ArraryList没有关系

② 类SuperA是类A的父类或接口,SuperA与A的关系:SuperA与A有继承或实现关系

比如:List与ArrayList

类型必须保持一致

通配符 :?

使用说明

》举例:ArrayList

》G可以看成G类型的父类,既可以将G的对象赋值给G类型引用(或变量)

读写数据特点(以集合ArrayList为例)

》读取数据:允许的,读取的值的类型为Object类型

》写入数据:不允许,特例:但可以写入null值(因为类型未知)

有限制条件的通配符

List:可以将List或List赋值给List,其中B类是A类的子类

List:以将List或List赋值给List,其中B类是A类的父类

有限制条件的通配符的读写条件

你可能感兴趣的:(南城余的Java学习,java)