【Java学习笔记】泛型

泛型

一、泛型的引出

代码示例

public class pra {
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        arrayList.add("java");
        arrayList.add("jack");
        arrayList.add("jom");

        arrayList.add(new a());

        for (Object obj :arrayList) {
            String str = (String)obj;
            System.out.println(str);
        }
    }
}

class a{
    public a() {
    }
}

由于添加了 a 对象,但是在遍历的时候遍历的是字符串对象,这个时候就会抛出ClassCastException异常

问题总结

  • 不能对加入到集合 ArrayList 中的数据类型进行约束(不安全

  • 遍历的时候需要进行数据类型转换,如果集合的数据量大,对显效率有影响

总结:由于集合中添加的对象,当集合中的对象不为同一类对象时,遍历集合就会出现异常,这个时候可以通过泛型来约束集合存储的对象类型


二、泛型

1. 基本介绍

(1)泛型又称参数化类型,是 Jdk5.0 出现的新特性,解决数据类型的安全性问题

(2)在类声明或实例化时只要指定好需要的具体的类型即可。

(3)Java 泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生 ClassCastException 异常。同时,代码更加简洁、健壮

(4)泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型。

(5)泛型的理解:是一种表示数据类型的数据类型

2. 泛型的使用

(1)基本语法

单例集合

ArrayList<T> arrylist = new ArrayList<T>()

双例集合

HashMap<K,V> arrylist = new HashMap<K,V>()

推荐写法

ArrayList<String> arrylist = new ArrayList<>()

说明:T、K、V 不代表值(可以替换成其他任意字母),而是表示类型

(2)应用场景

1. 接口

interface 接口名<T>{

}

2. 类

class<K,T....>{

}

注意:类中可以有多个泛型变量

3. 泛型的优点

  • 编译时,检查添加元素的类型,提高了安全性

  • 减少了类型转换的次数,提高效率

  • 不再提示编译警告

4. 泛型的使用细节

  • 泛型变量只能是引用类型错误的例子:List<int> list = new ArrayList<int>()

  • 给泛型指定具体类型后,可以传入该类型或者其子类型(理解:该集合只能存储指定的类型和子类型)

  • 如果不写泛型默认是Object类型,下方的两条语句等价

ArrayList list = new ArrayList();

ArrayList<Object> list = new ArrayList<>()

传入子类型的说明

public class pra {
    public static void main(String[] args) {
        animal<a> a = new animal<a>(new a());
        animal<a> b = new animal<a>(new b());
    }
}

class a{

}

class b extends a{

}

class animal<T>{
    T e;

    // 构造器
    public animal(T e){
        this.e = e;
    }

    public void getclass(){
        System.out.println(e.getClass());
    }
}

说明:指定了animal类只能存储 a 类对象,但是 b 类是 a 的子类,即 animal 类既可以是 a 对象也可以是 b 对象

5. 简单的泛型案例

public class pra {
    public static void main(String[] args) {
        HashMap<String,student> hashMap = new HashMap<>();
        hashMap.put("18",new student("jackson"));
        hashMap.put("20",new student("jack"));
        hashMap.put("23",new student("jom"));

        // 先取出entryset
        Set<Map.Entry<String, student>> entries = hashMap.entrySet();

        // 构建迭代器(指向单例集合)
        Iterator<Map.Entry<String, student>> iterator = entries.iterator();

        while (iterator.hasNext()) {
            Map.Entry<String, student> next = iterator.next();
            System.out.println("key:" + next.getKey() + " value:" + next.getValue());
        }
    }
}

class student{
    String name;

    public student(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "student{" +
                "name='" + name + '\'' +
                '}';
    }
}

通过指定 HashMap 存储键值对的类型,然后遍历集合查看存储结果


三、自定义泛型类

1. 基本介绍

(1) 普通成员可以使用泛型(属性、方法)

(2) 使用泛型的数组,不能初始化(由于不知道数组的类型,无法在内存开辟空间)

(3) 静态方法中不能使用类的泛型

  • 因为静态是和类相关的,在类加载时,对象还没有创建

  • 如果静态方法和静态属性使用了泛型,JVM 就无法完成初始化

(4) 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)

(5) 如果在创建对象时,没有指定类型,默认为 Object

(6)泛型是标识符,需要大写

结构示例

class a<T,K,V...>{
    T age;
    K name;
    V phone_number;
    ...
}

四、自定义泛型接口

(1) 接口中,静态成员也不能使用泛型

(2) 泛型接口的类型,在继承接口或者实现接口时确定

(3) 没有指定类型,默认为 Object

(4)如果一个类实现了泛型接口,需要实现接口中的方法并且需要指定接口方法中的泛型类型

代码示例

public class pra {
    public static void main(String[] args) {

    }
}

interface a<T,R>{
    // 接口中的变量默认是静态的,需要赋初值

    void hi(T t,R r);

    void pay(T t,R r);

    void run(T t,R r);
}

class b implements a<String,Double>{
    @Override
    public void hi(String s, Double aDouble) {

    }

    @Override
    public void pay(String s, Double aDouble) {

    }

    @Override
    public void run(String s, Double aDouble) {

    }
}

代码分析

通过指定泛型的类型来实现接口中的方法


五、自定义泛型方法

(1)实体信息为泛型方法的定义位置相关内容,泛型方法可定义在普通类或泛型类中

(2)泛型方法调用时确定类型(通过传入的参数自动判断是什么类型)

(3)若修饰符后无 <T,R...> ,像 public void eat(E e) {} 不是泛型方法,只是方法参数使用了泛型


六、泛型的继承和通配符

(1)泛型不具备继承性(错误案例:List<Object> list = new ArrayList<String>()

(2) <?> : 支持任意泛型类型

(3) <? extends A> : 支持 A 类以及 A 类的子类,规定了泛型的上限

(4) <? super A> : 支持 A 类以及 A 类的父类,不限于直接父类,规定了泛型的下限

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jackson凌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值