简体   繁体   English

下限通配符Java - 访问方法

[英]Lower-Bounded Wildcards Java - Access to Methods

I understand that one reason Lower-bounded wildcards exist is so that a collection is not immutable when adding new elements. 我理解,存在低限通配符的一个原因是,在添加新元素时,集合不是不可变的。

Eg 例如

List<? extends Number> obj = new ArrayList<>();//Now this list is immutable
obj.add(new Integer(5));//Does not compile
List<? super Number> objTwo = new ArrayList<>();//This list is mutable
objTwo.add(new Integer(5));//Compiles

The following does not compile because I tried to get the long value of numbers. 以下不编译因为我试图得到数字的长值。

Q1: What methods would I be able to use? Q1:我可以使用哪些方法? Only Objects methods?: 只有Objects方法?:

public void testLowerBounds(List<? super Number> numbers){
        if (!numbers.isEmpty()){
           System.out.println(numbers.get(0).longValue());//Does not compile
        }    

} }

How my question came about: I am currently learning about streams and the book specifies the following stream method: 我的问题是如何产生的:我目前正在学习流,本书指定了以下流方法:

Optional<T> min(Comparator<? super T> comparator)

And implements it as follows: 并实现如下:

Stream<String> s = Stream.of("monkey", "ape", "bonobo");    
Optional<String> min = s.min((s1, s2) -> s1.length()—s2.length());

Q2: How is the comparator allowed to use string methods when is used? Q2:比较器在使用时如何允许使用字符串方法?

If I had to answer Q2: I would say that optional is specifying "You have to pass me an implementation of Comparator that has a generic type "String" or something that implements "String". Would I be correct in saying this? 如果我必须回答Q2:我会说可选是指定“你必须传递一个具有泛型类型”字符串“的比较器的实现或者实现”字符串“的东西。我会说这个是正确的吗?

Looking forward to your response. 期待你的回复。

First of all, you should not confuse wildcard type parameters with mutability. 首先,您不应将通配符类型参数与可变性混淆。 Having a wildcard in a List 's element type does not prevent modifications, it only imposes a few practical restrictions to what you can do with the list. List的元素类型中使用通配符不会阻止修改,它只对您可以对列表执行的操作施加一些实际限制。

Having a list declared like List<? extends Number> 将列表声明为List<? extends Number> List<? extends Number> implies that the referenced list has an actual element type of Number or a subclass of Number , eg it could be a List<Integer> or List<Double> . List<? extends Number>意味着引用列表具有的实际的元件类型Number或子类Number ,例如,它可能是一个List<Integer>List<Double> So you can't add an arbitrary Number instance as you can't know whether it is compatible to the actual element type. 因此,您无法添加任意Number实例,因为您无法知道它是否与实际元素类型兼容。

But you can still add null , as the null reference is known to be compatible with all reference types. 但是您仍然可以添加null ,因为已知null引用与所有引用类型兼容。 Further, you can always remove elements from a list, eg call remove or clear without problems. 此外,您始终可以从列表中删除元素,例如调用removeclear而不会出现问题。 You can also call methods like Collections.swap(list, index1, index2) , which is interesting as it wouldn't be legal to call list.set(index1, list.get(index2)) due to formal rules regarding wildcard types, but passing the list to another method that might use a non-wildcard type variable to represent the list's element type works. 您还可以调用Collections.swap(list, index1, index2) ,这很有意思,因为有关通配符类型的正式规则调用list.set(index1, list.get(index2))是不合法的,但是将列表传递给另一个可能使用非通配符类型变量来表示列表元素类型的方法。 It's obviously correct, as it only sets elements stemming from the same list, which must be compatible. 这显然是正确的,因为它只设置源自同一列表的元素,这些元素必须兼容。

Likewise, if you have a Comparator<Number> , you can call Collections.sort(list, comparator) , as a comparator which can handle arbitrary numbers, will be able to handle whatever numbers are actually stored in the list. 同样,如果你有一个Comparator<Number> ,你可以调用Collections.sort(list, comparator)作为一个可以处理任意数字的比较器,能够处理列表中实际存储的任何数字。

To sum it up, having ? extends 总结一下,有? extends ? extends in a collection's element type does not prevent modifications. ? extends在集合的元素类型并不妨碍修改。


As said, you can't insert arbitrary new elements into a list whose actual element type might be an unknown subclass of the bound, like with List<? extends Number> 如上所述,您不能将任意新元素插入到实际元素类型可能是绑定的未知子类的List<? extends Number> ,例如List<? extends Number> List<? extends Number> . List<? extends Number> But you are guaranteed to get a Number instance when retrieving an element, as every instance of subtype of Number is also an instance of Number . 但是您可以保证在检索元素时获得Number实例,因为Number每个子类型实例也是Number的实例。 When you declare a List<? super Number> 当你声明一个List<? super Number> List<? super Number> , its actual element type might be Number or a super type of Number , eg Object or Serializable . List<? super Number> ,它的实际元素类型可能是Number或超类型的Number ,例如ObjectSerializable You can insert arbitrary Number instances, as you know it will be compatible to whatever actual element type the list has, as it is a super type of number. 您可以插入任意Number实例,因为您知道它将与列表具有的任何实际元素类型兼容,因为它是超类型的数字。 When you retrieve an instance, you only know that it is an instance of Object , as that's the super type of all instances. 检索实例时,您只知道它是Object的实例,因为它是所有实例的超类型。 To compare with the ? extends 要比较? extends ? extends case, having a ? super ? extends案例,有一个? super ? super declaration does not prevent reading, it only imposes some practical limitations. ? super声明不会阻止阅读,它只会带来一些实际限制。 And likewise, you can still pass it to Collections.swap , because, regardless of how little we known about the actual type, inserting what we just retrieved from the same list, works. 同样,你仍然可以将它传递给Collections.swap ,因为无论我们对实际类型知之甚少,插入我们刚从同一列表中检索到的内容都可行。

In your second question, you are confusing the sides. 在你的第二个问题中,你让双方感到困惑。 You are now not looking at the implementation of min , but at the caller . 你现在不是在看min的实现,而是在调用者处 The declaration of min(Comparator<? super T> c) allows the caller to pass any comparator being parameterized with T or a super type of T . min(Comparator<? super T> c)允许调用者传递任何使用T或超类型T参数化的比较器。 So when you have a Stream<String> , it is valid to pass a Comparator<String> to the min method, which is exactly, what you are implementing via the (s1, s2) -> s1.length()—s2.length() lambda expression (though, I'd prefer Comparator.comparingInt(String::length) ). 所以当你有一个Stream<String> ,将Comparator<String>传递给min方法是有效的,这正是你通过(s1, s2) -> s1.length()—s2.length() lambda表达式(但是,我更喜欢Comparator.comparingInt(String::length) )。

Within the implementation of min , there is indeed no knowledge about what either, T or the actual type argument of the Comparator , is. min的实现中,确实不知道Comparator T或实际类型参数是什么。 But it's sufficient to know that any stream element that is of type T can be passed to the comparator's compare method, which might expect T or a super type of T . 但是,知道任何类型为T流元素都可以传递给比较器的compare方法,这可能需要T或超类型的T ,这就足够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM