java泛型中的PECS原则Producer extend consumer super和上限和下限解释

关注公众号:”奇叔码技术“

回复:“java面试题大全”或者“java面试题”
即可免费领取资料




一、适用场景:学好了能够看懂Stream类中的一些方法参数;了解概念:限制上限【可以返回值】和下限【可以添加值】和PECS原则【限制了数据的放入和取出。】


1、什么叫上限?

//上限:这个箱子容器最大为100,但是具体可以放多小的东西谁也不知道,放80,79,40,最后确定它可以放30,那都错误了,所以,没有明确的说明,那就不可以放东西为100以下的;
// 例如:我看起来最大20岁,那你可以说我18,19,15都行,但是如果我是15,那18和19就错误了;


//但是,这个箱子容器最大为100,我可以拿一个100的容器或者200的容器总之大于等于100的容器,把它装起来,所以,它是用来取即有返回值,不能放;


//又,生产者是不断创造东西得,上限就像工厂里面生产东西 【返回东西】,他就是生产者;

2、什么叫下限?

//同理:
// 下限:这个箱子容器最小为100,那我可以放比100还小的东西进去;我可以放80都行;所以,它是用来放得,不是用来取得;


//又,消费者是用东西的;下限就是我有钱,我去银行存钱,我就把钱消费给了银行;【感觉不恰当】

二、通配符<?>和类型参数T、K、V的区别?

//通配符<?>和类型参数的区别就在于,对编译器来说所有的T都代表同一种类型。比如泛型方法里,三个T都指代同一个类型,要么都是String,要么都是Integer。
//但通配符<?>没有这种约束,List<?>单纯的就表示:集合里放了一个东西,是什么我不知道。
//实际就是类型参数指明了类型,编译器知道你是什么类型;
//通配符<?>没有约束,是什么类型的我是问号不知道的,所以不能放东西;
//如果是<? extends Father > 指明上限是Father,而?是它的子类或者就是Father;


//如果是需要获取值,那就只能是利用 多态 返回的类型必须是它的基类【即父类或者自己】

三、PECS原则

/*PECS原则【限制了数据的放入和取出。】
最后看一下什么是PECS(Producer Extends Consumer Super)原则,已经很好理解了:
频繁往外读取内容的,适合用上界Extends。知道上界限 即 可以通过多态向上转型 返回其基类 Object、父类、自己、
经常往里插入的,适合用下界Super。 知道下界限 即 可以通过多态向上转型 添加其子类 子类、自己;

PESC = producer-extens , consumer -super.
如果参数化类型表示一个 T 生产者,就使用 <? extends T>; 如果它表示一个 T 消费者, 就使用 <? super T>
PESC 这个助记符突出了通配符类型的基本原则。(Get and Put Principle)

范型为List<?extends A> list,确定了上界为A,list是一个生产者,可以从list中取出数据;
为List<? super A> list,确定了下界,list 中的数据类型为A 或者A的父类,list是一个消费者:

四、上代码:

package com.jiqi.Stream;

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

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


    }
    //<? super Father> ?比 Father还要super【大】 那Father就是最小的,即下界限 那可以放比Father还要小的;
    public void floorLimit(){
        ArrayList<? super Father> list = new ArrayList<>();
        boolean add = list.add(new Son());
        boolean add1 = list.add(new Father());
        boolean add2 = list.add(new LeiFeng());
        System.out.println(add);
        System.out.println(add1);
        System.out.println(add2);
        Object object = list.get(0);
        System.out.println(object);
    }
    //<? extends Father> ?继承于 Father 比Father 【小】 naFather就是最大的,即上界限 那可以返回比Father大的;
    public void upLimit(){
        List<? extends Father> list = new LinkedList<>();
        // list.add(new Son()); 报错,虽然是它的子类,符合 son extends Father ;
        // 但由于?通配符 是一个问号他不知道里面放了什么东西,所以编译报错;

        //赋值是合法的
        List<? extends Father> list1 = new ArrayList<Father>();
        List<? extends Father> list2 = new ArrayList<Son>();
        List<? extends Father> list3 = new ArrayList<LeiFeng>();
        //取值可以,只能利用多态的形式 进行获取;
        Object o  = list.get(0);
        Father f  = list.get(0);
        Human h  = list.get(0);
        //上界<? extends T>不能往里存,只能往外取
    }
}
class Human{
}
class Father extends Human{
}
class Son extends Father{
}
class LeiFeng extends Father {
}

点击跳转学习大佬的借鉴题目:Java中<? extends T>和<? super T>的理解#

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java泛型extendsuper是用于限制泛型类型参数的关键字。 extend用于限制泛型类型参数的上界,表示泛型类型参数必须是指定类型的子类或实现类。例如,List<? extends Number>表示泛型类型参数必须是Number类或其子类。 super用于限制泛型类型参数的下界,表示泛型类型参数必须是指定类型的父类或超类。例如,List<? super Integer>表示泛型类型参数必须是Integer类或其父类。 使用extendsuper可以使泛型类型参数更加灵活,可以适应不同的场景需求。但是需要注意的是,使用过多的extendsuper可能会导致代码可读性降低,因此需要根据实际情况进行选择和使用。 ### 回答2: Java可以通过泛型实现更强大的类型安全和代码的复用性。在使用泛型时,我们常常需要了解泛型extendsuper关键字,以便更好地理解和使用。 泛型extend关键字 泛型extend关键字用于限定泛型类型参数的上限,表示泛型类型参数必须是继承了某个类或实现了某个接口才能被使用。例如: ``` public class GenericClass<T extends Number> { private T data; public GenericClass(T data) { this.data = data; } public T getData() { return data; } } ``` 在上面的泛型,使用了T extends Number语法,表示泛型类型参数T必须是继承了Number类的某个子类,否则编译会报错。这样可以保证data属性的类型一定是Number或其子类类型。 泛型super关键字 泛型super关键字用于限定泛型类型参数的下限,表示泛型类型参数必须是某个类的父类或某个接口的实现类。例如: ``` public class GenericClass<T super Number> { private T data; public GenericClass(T data) { this.data = data; } public T getData() { return data; } } ``` 在上面的泛型,使用了T super Number语法,表示泛型类型参数T必须是Number类的父类,即可以是Number类本身或其父类类型。这样可以保证data属性的类型一定是Number类或其父类类型。 需要注意的是,泛型extendsuper关键字只能用于泛型类型参数,而不能用于普通类型。在实际使用,我们需要根据具体的情况来灵活地使用泛型extendsuper关键字,以便在代码实现更好的类型安全和更高的代码复用性。 ### 回答3: Java泛型是一种非常强大的语言特性,允许我们使用一种类型来表示多种类型,在编写类型安全且可重用的代码时经常用到。在泛型的使用,我们有时需要约束所能使用的泛型类型,使得代码更加类型安全。在这种情况下,我们可以使用泛型extendsuper 关键字。 在 Java ,使用 extends 关键字可以为泛型类型参数添加上限限制。通过 extends 关键字,我们可以指定泛型类型参数必须是某个类或接口的子类。这样做的好处是能够防止代码使用无效的类型参数,从而保证代码的类型安全性。值得注意的是,我们只能使用 extends 关键字来添加上限限制,而不能添加下限限制。 下面是一个例子,演示如何使用 extends 关键字: ``` public class Box<T extends Number> { private T t; public Box(T t) { this.t = t; } public T get() { return t; } public void set(T t) { this.t = t; } } ``` 可以看到,Box 类使用了 extends 关键字,将泛型类型参数 T 限制为 Number 类型或其子类型。在此之后,我们就可以在 Box 类安全地使用 Number 类型或其子类型,如 Integer、Double 等。 除了上限限制之外,Java 还提供了另一种泛型类型参数的约束方式:super 关键字。使用 super 关键字,我们可以限制泛型类型参数必须是某个类或接口的父类。这个约束通常用于需要消费泛型对象的情况,例如集合类的 add 方法。通过为泛型类型参数添加 super 关键字,我们可以保证只能添加某个类的子类到集合,从而防止集合出现无效的元素。类似地,我们也只能使用 super 关键字添加下限限制,而不能添加上限限制。 这里是一个例子,演示如何使用 super 关键字: ``` public class Box<T> { private List<? super T> list; public Box() { list = new ArrayList<>(); } public void add(T t) { list.add(t); } public void addAll(List<? extends T> otherList) { list.addAll(otherList); } } ``` 可以看到,Box 类使用了 super 关键字来限定集合存储的类型,只能是 T 的父类或其本身。这样做的好处是,保证添加到集合的元素都是类型安全的,避免了程序运行时出现错误。 总之,泛型类型参数的 extendsuper 关键字是 Java 泛型使用的重要工具,能够帮助我们实现类型安全的代码。在实际使用,根据具体场景灵活运用这两个关键字,能够提高代码的可读性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值