gpt4 book ai didi

具有未知泛型接口(interface)的 Java 泛型编程

转载 作者:行者123 更新时间:2023-11-30 11:51:42 25 4
gpt4 key购买 nike

我正在使用多个具有泛型类型的接口(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
}
}

第一个问题:

  1. 考虑到 ClientClass 不关心扩展 Number 的具体类型是集合的事实,我应该在声明集合时带或不带“?” ?如果我使用第二个版本,我会收到以下警告:

MyCollectionInterface is a raw type. References to generic type LatticeInterface should be parameterized

第二个问题:

  1. 为什么方法 foo 不能编译?

第三个问题:

  1. 看来我需要使用 bar 签名来调用 updateObject 方法。无论如何,这个解决方案在尝试分配 MyObjectInterface 参数时会产生警告,就像第一个问题一样。我可以删除此警告吗?

最后的问题:

  1. 我是不是在用这个通用接口(interface)做一些奇怪的事情,我应该重构我的代码?
  2. 我真的需要关心所有这些警告吗?
  3. 如何在不知道其具体类型的类中安全地使用通用接口(interface)?

最佳答案

好的,我试了一下你的代码并得出了结论。

问题是你的 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>来自 MyCollectionInterfaceConcreteCollectionT不再使用了。

@你最后的问题:

1) 可能是
2) 你应该
3) 你不能,如果你真的不关心你在集合中存储哪些对象,你应该完全放弃泛型。

抱歉回答太长,希望对您有所帮助。

关于具有未知泛型接口(interface)的 Java 泛型编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7300163/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com