Java 去掉返回值中的通配符参数

Java 去掉返回值中的通配符参数,java,generics,wildcard,Java,Generics,Wildcard,我有一些代码在内部使用泛型。到目前为止一切都很好,直到功能通过公共API公开为止。这个问题与下面的玩具示例相同:我有一个带有特定子类型的包装项目的列表(T extends Number)。当我想返回这个列表时,我目前正在返回一个列表,据我所知,如果你想返回T,这是不可能的。当你想返回T时,你不能返回T的子类型。我刚刚发现以下方法有效。任何关于潜在缺陷的反馈和评论仍然非常感谢 public static List<Wrapper<Number>> getNumbers()

我有一些代码在内部使用泛型。到目前为止一切都很好,直到功能通过公共API公开为止。这个问题与下面的玩具示例相同:我有一个带有特定子类型的包装项目的
列表(
T extends Number
)。当我想返回这个
列表时,我目前正在返回一个
列表,据我所知,如果你想返回T,这是不可能的。当你想返回T时,你不能返回T的子类型。我刚刚发现以下方法有效。任何关于潜在缺陷的反馈和评论仍然非常感谢

public static List<Wrapper<Number>> getNumbers() {
    Wrapper<Integer> number1 = new Wrapper<Integer>(1);
    Wrapper<Double> number2 = new Wrapper<Double>(2.);
    List<Wrapper<? extends Number>> numbers = new ArrayList<Wrapper<? extends Number>>();
    numbers.add(number1);
    numbers.add(number2);
    return (List<Wrapper<Number>>)(List<?>)numbers;
}
公共静态列表getNumbers(){
包装编号1=新包装(1);
包装编号2=新包装(2);

根据您所显示的
包装器
类型,
包装器这是错误的。
包装器
不是
包装器
,即使
整数
是一个
数字
。因此,您所做的是对类型系统撒谎。此外,如果您要这样做,为什么不声明
数字1
number2
要成为
Wrapper
?那么你就不需要做任何疯狂的强制转换。在我的例子中,我使用的不是
number2
,而是我库中特定类型的子类型。通过API,我不想公开这些子类型存在的事实,但
?扩展的
恰恰表明了这一点。保持代码的简短和可读性是不可取的这是一个目标,但我同意“制作人”方面的观点。我理解这是“欺骗”,但你能告诉我实际的含义吗?另一个解决方案似乎是“重新包装”
numbers
中的所有项都放入一个新创建的
包装器中,但这真的不同吗?+1.OP应该更改客户端代码…或者更好,完全避免这种泛型滥用…@qqilihq:
?extends X
表示
X
或其子类型。这并不一定意味着存在
的子类型X
。例如,您可以编写
?扩展字符串
,但不能有任何字符串的子类型。从泛型的角度来看,您应该使用
?扩展
,因为代码中的任何内容都不依赖于正是该类型的类型参数。
public static List<Wrapper<Number>> getNumbers() {
    Wrapper<Integer> number1 = new Wrapper<Integer>(1);
    Wrapper<Double> number2 = new Wrapper<Double>(2.);
    List<Wrapper<? extends Number>> numbers = new ArrayList<Wrapper<? extends Number>>();
    numbers.add(number1);
    numbers.add(number2);
    return (List<Wrapper<Number>>)(List<?>)numbers;
}