泛型被go 掉了一个元级别.你需要站在编者的立场上走一步才能理解它们.
我经常看到泛型的错误,你似乎也犯了这样的错误,你认为Predicate<? extends Person>
意味着‘这是一个可以测试任何人的谓词.一个员工,一个客户-并不重要,因此,’任何扩展人‘都是正确的.
But that is not what that means.
毕竟,想象一下这意味着什么.那么Predicate<Person>
是什么呢?一个只能专门测试new Person()
而不能测试new Employer()
的谓词?Java不是这样工作的--Employer的任何实例都可以用作Person,所以这将是非常奇怪的.
事实上,Predicate<Person>
在这里的意思就是您想要的:可以是test any person的谓词对象.
那么Predicate<? extends Person>
是什么意思呢?这一点:
可以测试的谓词...我真的不知道它能测试什么.我所知道的是,无论它是什么,它都是某种类型,要么是人,要么是其子类型.
那么,这样的事情有什么意义呢?在这个特定的情况下(对于谓词)并不是很多.让我们转而考虑列表.我们有3种不同的相关类型(记住,Integer和Double都是扩展数字,数字扩展对象)
List<? extends Number>
个
List<? super Number>
个
List<Number>
个
您可以将List<Integer>
对象传递给接受List<? extends Number>
个的方法.将它传递给一个接受List<Number>
个的方法.为什么不-整数扩展了数字,对吗?啊,但是inside generics,这是不变的,比如,不,你不能只是用子类型替换一个类型.毕竟,我可以将Double
对象加到List<Number>
个上.我可以将数字宾语添加到我的列表中,双重宾语是数字宾语,Qed.
但是,在List<Integer>
的基础上加上一个双重对象,这是不好的.因此,List<? extends Number>
个是必需的--试试看,您cannot会向这样的列表中添加内容.出于同样的原因:List<? extends Number>
个并不意味着:"一个可以容纳数字的列表--任何数字".恰恰相反.它的意思是:"一个可以容纳的列表……我不知道它能容纳什么(因此有问号!)--我只知道,无论它容纳什么,它都是数字.或者数字的任何子类).考虑到这一点,list.get(5)
将返回一个Number
类型的表达式(考虑到我们所知的少数几件事,这是安全的),但你不能向它添加任何东西(除了字面null
的理论用例,它是所有类型).
特别是对于Predicate
,Predicate<? extends>
是完全没有用的,无论如何都不应该出现.Predicate<? super X>
可能会很方便.毕竟,这意味着:"一个可以测试的谓词……我不知道它可以测试什么.我所知道的是,它要么是X,要么是super种类型的X".考虑到这些信息,.test(instanceOfX)
是可以接受的.