【发布时间】:2018-02-26 16:59:14
【问题描述】:
假设我有一个泛型类Foo,它可以容纳T 类型的对象。此外,假设我仅希望能够使用属于两种类型之一的对象来实例化该类。最后,假设这两种类型的最低公共上界是一个比我想要允许的这两种类型有更多子类的类型,所以我不能简单地为类型参数指定一个上限(如@ 987654324@),因为这样我就可以用我期望的两种类型之外的其他类型来实例化该类。
为了说明,假设我希望Foo 仅保存String 或Integer。最低的公共上限是Object,因此指定一个上限并不能解决问题。
当然,我可以做一些类似的事情
class Foo<T> {
private T obj;
public Foo(T obj) throws IllegalArgumentException {
if (!(obj instanceof String || obj instanceof Integer)) {
throw new IllegalArgumentException("...");
}
this.obj = obj;
}
}
但是,在这种情况下,我仍然可以使用 any 对象调用构造函数;如果我尝试使用既不是 String 也不是 Integer 的东西来实例化它,我将在 runtime 时遇到异常。
我想做得更好。我希望编译器静态推断(即在编译时)我只能使用String 或Integer 的对象来实例化这个类。
我在想一些类似的东西可能会奏效:
class Foo<T> {
private T obj;
public Foo(String s) {
this((T) s);
}
public Foo(Integer i) {
this((T) i);
}
private Foo(T obj) {
this.obj = obj;
}
}
这行得通,但它看起来非常非常奇怪。编译器警告(可以理解)未经检查的强制转换。当然我可以压制这些警告,但我觉得这不是要走的路。此外,看起来编译器实际上无法推断类型T。我惊讶地发现,使用 Foo 类的后一个定义,我可以这样做,例如:
Foo<Character> foo = new Foo<>("hello");
当然,这里的类型参数应该是String,而不是Character。但是编译器让我摆脱了上述任务。
- 有没有办法实现我想要的,如果有,如何实现?
- 附带问题:为什么编译器允许我在没有 警告 的情况下对上述
Foo<Character>类型的对象进行赋值(当使用类 @987654341 的后一个定义时) @)? :)
【问题讨论】:
-
谢谢。我实际上无权访问
A或B,所以我不能让它们实现接口。 ://
标签: java class generics java-8