Java 泛型中的PECS原则

问题

今天看到一个网友抛出这样一个问题:

package Generics;

import java.util.ArrayList;
import java.util.List;

/**
 * @Classname PECS
 * @Description TODO
 * @Date 2022/5/22 21:44
 * @Created by YJS
 * @WebSite www.imyjs.cn
 */
public class PECS {
    public static void main(String[] args) {
        List<? extends A> list = new ArrayList<>();
        list.add(new B()); // 在IDEA下会自动提示错误
    }
}

class A{}

class B extends A{}

class C extends B{}

 

代码执行后会抛出如下提示:

// java: 对于add(Generics.B), 找不到合适的方法
//    方法 java.util.Collection.add(capture#1, 共 ? extends Generics.A)不适用
//      (参数不匹配; Generics.B无法转换为capture#1, 共 ? extends Generics.A)
//    方法 java.util.List.add(capture#1, 共 ? extends Generics.A)不适用
//      (参数不匹配; Generics.B无法转换为capture#1, 共 ? extends Generics.A)

 

解决

将上面代码这样写就解决问题:

package Generics;

import java.util.ArrayList;
import java.util.List;

/**
 * @Classname PECS
 * @Description TODO
 * @Date 2022/5/22 21:44
 * @Created by YJS
 * @WebSite www.imyjs.cn
 */
public class PECS {
    public static void main(String[] args) {
        List<? super A> list1 = new ArrayList<>();
        list1.add(new B());
        list1.add(new C());
        System.out.println(list1.size());  // 2
    } 
}

class A{}

class B extends A{}

class C extends B{}

 

PECS

当我们在Java编程时,如果遇到不确定的数据类型时,我们可以是使用Object类型来接收参数,但是这种方法会有许多问题,此时我们可以借助JDK1.5后增加的泛型,在泛型机制中提供了通配符的概念。

<?>:无界通配符

<? extends T>:上界通配符

<? super T>:下界通配符

 

PECS原则:

Producer Extends Consumer Super

当需要频繁取值,而不需要写值则使用" ? extends T "作为数据结构泛型。

当需要频繁写值,而不需要取值则使用" ? super T "作为数据结构泛型。

这个是 Effective Java中提出的一种概念。

如果类型变量是生产者,则用 extends ,如果类型变量是消费者,则使用 super

这种方式也成为 Get and Put Principle。 即get属于生产者,put属于消费者.

<? extends T>

使用<? extends T>规定泛型的数据结构,我们知道其存储的值是T的子类,T可以有多个不同表现的子类(多态),因此当我们进行写值时,我们并不知道其中存储的到底是哪个子类,不同子类是不同的类型,因此写值操作必然会出现问题,所以编译器直接禁止在使用<? extends T>泛型的数据结构中进行写值,只能进行取值,正是开头所说的PE原则。

<? super T>

对于使用<? super T>规定泛型的数据结构,我们只知道其存储的值是T的父类,若以T为数据类型取值时 T t = ?,等于将父类(?)当做子类(T)使用,这显然是不合理的,父类缺少子类中的一些信息,因此编译器直接禁止在使用<? super T>泛型的数据结构中进行取值,只能进行写值,正是开头所说的CS原则。

总结

当使用extends做泛型时,该数据结构作为Producer对外提供值,只能进行取值而不能写值。
当使用super做泛型时,该数据结构作为Producer对外提供值,只能进行取值而不能写值。

 

参考阅读:

 

微信关注

编程那点事儿

本站为非盈利性站点,所有资源、文章等仅供学习参考,并不贩卖软件且不存在任何商业目的及用途,如果您访问和下载某文件,表示您同意只将此文件用于参考、学习而非其他用途。
本站所发布的一切软件资源、文章内容、页面内容可能整理来自于互联网,在此郑重声明本站仅限用于学习和研究目的;并告知用户不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
如果本站相关内容有侵犯到您的合法权益,请仔细阅读本站公布的投诉指引页相关内容联系我,依法依规进行处理!
作者:理想
链接:https://www.imyjs.cn/archives/851
THE END
二维码
Java 泛型中的PECS原则
问题 今天看到一个网友抛出这样一个问题: package ……
<<上一篇
下一篇>>
文章目录
关闭
目 录