- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用多个具有泛型类型的接口(interface)。将它们组合在一起时,当我不得不从不知道通用参数的具体类型的代码部分使用它们时,我遇到了一些问题。
假设我有以下界面:
public interface MyObjectInterface<T extends Number> {}
实现该接口(interface)的对象存储在具有相同泛型类型的泛型集合中:
public interface MyCollectioninterface<T extends Number> {
public void updateObject(MyObjectInterface<T> o);
}
MyCollectionInterface 的具体实例包含多个具有相同通用参数的 MyObjectInterface:
public class ConcreteCollection<T extends Number> implements
MyCollectionInterface<T> {
List<MyObjectInterface<T>> list;
public void updateObject(MyObjectInterface<T> o){}
}
现在,我有几个关于如何从客户端类使用这些通用接口(interface)的问题(并且必须)不知道泛型的具体类型。
假设我有以下类(class):
public class ClientClass{
private MyCollectionInterface<?> collection; //1st possibility
private MyCollectionInterface collection; //2nd possibility
public ClientClass(MyCollectionInterface<?> collection){
this.collection = collection;
}
public void foo(MyObjectInterface<?> o){
this.collection.updateObject(o); //this doesn't compile
}
public void foo(MyObjectInterface<? extends Number> o){
this.collection.updateObject(o); //this doesn't compile either
}
public void bar(MyObjectInterface o){
MyObject b = o; //warning
this.collection.updateObject(o); //this compile but with warnings
}
}
第一个问题:
MyCollectionInterface is a raw type. References to generic type LatticeInterface should be parameterized
第二个问题:
第三个问题:
最后的问题:
最佳答案
好的,我试了一下你的代码并得出了结论。
问题是你的 ConcreteCollection
(及其接口(interface) MyCollectionInterface
)声明方法 updateObject
接收类型为 MyObjectInterface<T>
的参数(其中 T extends Number
)- 请注意类型是具体类型(不是通配符)。
现在,在您的客户端类中,您正在接收一个集合并将其存储为 MyCollectionInterface<?>
但是传递给ClientClass
的实例' 构造函数将是具体类型,例如:
new ClientClass(new ConcreteCollection<Integer>());
这意味着方法updateObject
该实例的只接受 MyCollectionInterface<Integer>
类型的参数.
然后,在方法foo
你正试图传递 MyObjectInterface<?>
至 updateObject
,但由于编译器不知道您的集合接受哪种泛型类型(它可能是 Integer
,就像我的示例中的那样,但它也可能是 Double
或扩展 Number
的任何其他类型),它 获胜'允许传递任何对象。
长话短说,如果您将引用声明为 MyCollectionInterface<?>
你将无法调用 updateObject
在上面。所以你有两个选择:
1) 选择一个具体的类型并坚持下去:
private MyCollectionInterface<Number> collection;
public ClientClass(MyCollectionInterface<Number> collection){
this.collection = collection;
}
public void foo(MyObjectInterface<Number> o){
this.collection.updateObject(o); //compiles
}
但是你限制了你可以在你的构造函数中接收的集合(这可能不是一个坏主意),或者:
2)修改您的界面以接受通配符类型:
public interface MyCollectionInterface<T extends Number> {
public void updateObject(MyObjectInterface<? extends Number> o);
}
public class ConcreteCollection<T extends Number> implements MyCollectionInterface<T> {
List<MyObjectInterface<T>> list;
public void updateObject(MyObjectInterface<? extends Number> o) {}
}
private MyCollectionInterface<?> collection;
public ClientClass(MyCollectionInterface<?> collection){
this.collection = collection;
}
public void foo(MyObjectInterface<?> o){
this.collection.updateObject(o); //compiles
}
另请注意,即使在 2) 中,您在执行 updateObject
时仍可能遇到同样的问题。方法,除非你声明你的 list
像这样的东西(以 ArrayList
为例):
List<MyObjectInterface<? extends Number>> list = new ArrayList<MyObjectInterface<? extends Number>>();
在这种情况下,您也可以删除 <T extends Number>
来自 MyCollectionInterface
和 ConcreteCollection
自 T
不再使用了。
@你最后的问题:
1) 可能是
2) 你应该
3) 你不能,如果你真的不关心你在集合中存储哪些对象,你应该完全放弃泛型。
抱歉回答太长,希望对您有所帮助。
关于具有未知泛型接口(interface)的 Java 泛型编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7300163/
我是一名优秀的程序员,十分优秀!