Java泛型如何实现协变和逆变

发布时间:2025-04-26 23:43:50 作者:小樊
来源:亿速云 阅读:103

在Java中,泛型的协变和逆变是通过使用通配符?extendssuper关键字来实现的。协变(covariance)允许你使用一个比原始指定的派生类型更具体的类型,而逆变(contravariance)允许你使用一个比原始指定的派生类型更泛化的类型。

协变(Covariance)

协变允许你使用一个更具体的类型来替换泛型参数。在Java中,这可以通过使用通配符? extends T来实现。这意味着你可以读取数据,但不能写入数据(除了null)。

public class CovarianceExample {
    public static void main(String[] args) {
        List<Integer> integers = Arrays.asList(1, 2, 3);
        List<Number> numbers = integers; // 协变
        // numbers.add(4); // 编译错误,不能写入数据

        Number number = numbers.get(0); // 读取数据是允许的
    }
}

逆变(Contravariance)

逆变允许你使用一个更泛化的类型来替换泛型参数。在Java中,这可以通过使用通配符? super T来实现。这意味着你可以写入数据,但不能保证读取的数据类型安全(只能保证它是T或T的父类)。

public class ContravarianceExample {
    public static void main(String[] args) {
        List<Number> numbers = new ArrayList<>();
        List<Object> objects = numbers; // 逆变
        objects.add(new Object()); // 写入数据是允许的

        Number number = numbers.get(0); // 读取数据是允许的,但可能不是最具体的类型
    }
}

通配符的限制

使用通配符?时,有一些限制:

  1. 不能实例化通配符类型的对象,例如new List<?>()是不允许的。
  2. 不能将通配符类型的对象赋值给非通配符类型的变量,例如List<?> list = new ArrayList<Integer>();是允许的,但List<Integer> list = new ArrayList<?>();是不允许的。
  3. 不能在泛型方法或类中使用通配符作为类型参数的上界或下界,除非是在声明通配符本身时。

泛型方法中的协变和逆变

泛型方法也可以使用协变和逆变:

public static <T> void copy(List<? super T> dest, List<? extends T> src) {
    for (T t : src) {
        dest.add(t);
    }
}

在这个例子中,copy方法的第一个参数是逆变的,因为它接受TT的父类的列表。第二个参数是协变的,因为它接受TT的子类的列表。

通过这种方式,Java的泛型系统提供了灵活的类型安全机制,允许在不同的场景下重用代码,同时保持类型的一致性和安全性。

推荐阅读:
  1. Java中Final能修饰哪些类型
  2. Java Final变量如何初始化

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:Java泛型中的协变与逆变是什么

下一篇:Java泛型如何提高代码的可读性

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》