繁体   English   中英

java泛型边界

[英]java generics bounds

我有以下代码:

public <T extends SomeObject> long doSomething(T someObject){
    List<? extends SomeObject> l = new LinkedList<>();
    l.add(someObject);
}

这会导致编译错误 - 告诉我找不到合适的方法:add(T),为什么会这样?

如果l接受扩展的东西SomeObject不应该接受someObject因为它SomeObject扩展SomeObject

List<? extends SomeObject> l

你是什​​么意思? 当然会产生错误。

举个例子: SomeObjectFruit ,你有2个派生类AppleOrange

你的清单包含哪些内容? Apple s还是Orange s? 编译器无法分辨。 所以它会产生错误。

如果你替换List<? extends SomeObject> l 使用List<SomeObject> l List<? extends SomeObject> l List<SomeObject> l 然后这将起作用,因为AppleOrange都是Fruit

我建议你使用这个声明:

List<T> l = new LinkedList<T>();

这样就不那么类型安全了

List<SomeObject> l = new LinkedList<SomeObject>();

此外,您还可以从列表中获取类型为T的对象,而无需进行强制转换。 T已经是SomeObject所以不需要在T上调用SomeObject的方法进行转换。所有这些都少了输入!

回到问题所在。

首先要注意的是通配符类型“?” 意思是未知 ,这很重要。 但是,您可以为其指定上限(?extends)或下限(?super)。 您将列表声明为“列表”。

已知List中包含SomeObject的对象。 但! 对象的确切类型未知。

编译器不能说列表中是否存在“A类扩展SomeObject”或“B类扩展SomeObject”的实例。 如果调用list.get(),它只能说会有SomeObject类型的对象。

SomeObject obj = list.get(1);   // Ok

但是插入任何(!)类型的对象是不安全的,因为列表中的实际元素类型是未知的。

您可能想知道为什么存在通配符类型。 这是为了降低类型铸造中的限制,否则将过于严格。

样品

class A { }

class A2 extends A { }

class B <T> {
    void change(T a) { .. };
    T read() { ..  };
}

如果没有通配符,我们将无法执行此操作: B<A> b = new B<A2>(); - 这是行不通的。 这是因为从B<A> to B<A2>类型转换是不安全的。

为什么? 我们来看看(复制自http://en.wikipedia.org/wiki/Generics_in_Java

List<Integer> ints = new ArrayList<Integer>();
ints.add(2);
List<Number> nums = ints;  // valid if List<Integer> were a subtype of List<Number>
nums.add(3.14);  
Integer x = ints.get(1);   // now 3.14 is assigned to an Integer variable!

解决办法是什么? 有时,我们希望以一般方式进行此类分配或传递参数!

通配符类型有助于: B<? extends A> b = new B<A2>(); B<? extends A> b = new B<A2>(); 方法B.void change(T a)现已禁用 - 这是您的问题在第一部分中解释和解释。

方法BT read()仍然有效并返回A: A a = b.read(); 是的,它实际上返回A2但是对于b.read()的调用者它是可见的A.

通配符类型在Collections Framework中广泛使用。

暂无
暂无

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

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