Java深入学习之 泛型程序设计

本文深入讲解了Java泛型的概念及应用,包括泛型类、泛型接口和泛型方法的定义与使用。同时探讨了类型擦除机制及其对泛型的影响,并通过实例展示了如何解决类型擦除与多态之间的冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 泛型概述

Java泛型在JSE 5.0提出。泛型,表示适用于更多的类型。类型参数化,使用一个类型参数,不指定确切的类型,在使用的时候指定类型,便可以不用只是因为类型不同而相同的代码。


2 泛型使用
2.1 泛型类
    public class GenericClass<T> {

    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

}

声明一个泛型类,在类名后面用<>扩起来泛型变量,需要用泛型变量表示的地方都用泛型变量。在Java的库中,E表示容器元素类型,T表示任意类型,K,V分别表示键值对的key,value。

2.2 泛型接口
public interface GenericInterface<T> {...}

声明一个泛型接口,与声明一个类名相似,在接口名后面用<>扩起来泛型变量E

2.3 泛型方法
public class GenericMethod {
    //泛型方法
    public <T> void add(T e) {}
}

声明一个泛型方法,需要在返回值前先引入泛型参数。泛型方法不是必须要在一个泛型类中,同样一个泛型类或接口中不是必须要有泛型方法。


3. 类型擦除

在Java的内部没有泛型类这个类型。泛型的实现机制实际上是类型擦除。类型擦除是编译器将参数类型替换成基本类型或者是限定类型,生成的泛型字节码仅有一份(不会因为类型不同而生成不同的代码)。在使用泛型的时候进行必要的类型检查或类型cast来保证最后获得的结果。

3.1 普通参数类型类

通过对泛型类GenericClass.java的反编译(javap -c -s GenericClass.class)
这里写图片描述
可以看到,在构造函数中会调用Object的构造函数。而且使用类型变量处,返回的变量都是java.lang.Object类型。说明在编译泛型类时,会将没有限定的泛型参数自动替换成Object(所有类的显示或隐式基类)

3.2 限定参数类型
    //限定的参数类型
    public class GenericWildcardClass<T extends Comparable<T>> {

    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

}

这里写图片描述
当类型参数有限定时,使用限定的第一个类型代替参数类型。

3.3 泛型方法

这里写图片描述
这里写图片描述
由编译后方法的描述符可以看出,泛型方法中的类型参数同样遵循没有限定的泛型参数用Object代替参数,有限定的泛型用第一个限定类或接口代替参数

3.4 多态遇上泛型参数
    public class GenericClass<T> {

    ...

    public void setValue(T value) {
        this.value = value;
    }

    public class GenericInheritanceClass extends GenericClass<Integer>{
        ...
    }

    public class GenericMain {

    public static void main(String[] args) {
        GenericClass<Integer> gic = new GenericInheritanceClass();
        gic.setValue(new Integer(0));
    }
}

gic 指向的是GenericClass类型,实际类型是GenericInheritanceClass。当调用setValue时,GenericClass中有的是setValue(Object)方法,而GenericInheritanceClass中类型擦除后是setValue(Integer)方法。 gic.setValue()应该调用的是GenericInheritanceClass中的方法,此时类型擦除与多态发生了冲突。编译器的解决方案是生成一个brige method, 也就是在GenericInheritanceClass中生成

    public void setValue(Object value) {
        setValue((Integer)value)
    } 

TODO

4. 泛型限制
5. 继承关系
6. 限定符
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值