[英]How can I use generics with exclusive bound using “extends”?
假设我在JDK 1.7下面有以下代码片段。 使用Generics,我很困惑如何使用extends
来实现具有独占 , 非包含边界的泛型参数化类型。 例如:
abstract class BaseAbstract {
}
class ChildWhichExtendsBaseAbstract extends BaseAbstract {
}
class SomeOtherClassWhichUseGenerics<T extends BaseAbstract> {
}
public class Test {
public static void main(String[] args) {
/**
* I just don't want JVM to compile below line, because I want to use
* generic type with {@link SomeOtherClassWhichUseGenerics} which must
* not be {@link BaseAbstract}
*/
SomeOtherClassWhichUseGenerics<BaseAbstract> obj1 =
new SomeOtherClassWhichUseGenerics<BaseAbstract>();
/**
* I just want JVM to compile below line, because I want to use generic
* type with {@link SomeOtherClassWhichUseGenerics} which must be only
* subclasses of BaseAbstract
*/
SomeOtherClassWhichUseGenerics<ChildWhichExtendsBaseAbstract> obj2 =
new SomeOtherClassWhichUseGenerics<ChildWhichExtendsBaseAbstract>();
}
}
我认为这应该是已知的问题/问题/要求之一。 有可能的工作吗?
extends
表示包含上限。 就是这样,讨论结束了。 没有办法说extends T
而不是T
来自JLS§4.5.1 :
类型参数T1被称为包含另一个类型参数T2,写为T2 <= T1,如果由T2表示的类型集合可证明是在以下规则的反身和传递闭包下由T1表示的类型集的子集(其中<:表示子类型( §4.10 )):
//剪断
- T <=? 延伸T.
而已。 T
包含在? extends T
? extends T
另外,即使你可以用这种方式绑定它,它也不会真的有用。 让我们说你可以; 这将是非法的:
public List<? exclusive-extends MyClass> list = new ArrayList<>();
list.add(new MyClass());
但是这个匿名类不会是:
public List<? exclusive-extends MyClass> list = new ArrayList<>();
list.add(new MyClass(){});
听起来像真正的问题是你不希望任何人将BaseAbstract
实例放入你的泛型类型中; 你只想要子类。
那么,这样做是很容易实现的; BaseAbstract
根本无法实例化,因为它是一个抽象类。 因此,只要参数化类型是抽象类,您就可以了。
如果你有一个真正的类,而不是一个抽象类,你可以简单地在它们之间放一个虚拟抽象类,例如
class Foo { }
abstract class AbstractFoo extends Foo { } // Newly added
class Bar extends AbstractFoo { } // previously extended Foo
class Baz extends AbstractFoo { } // previously extended Foo
我看到唯一的选择:使BaseAbstract
包私有并将所有子BaseAbstract
放在同一个包中。 这样就无法从外部访问BaseAbstract
。 例如,请考虑以下代码。
// a/BaseAbstract.java
package a;
abstract class BaseAbstract {
}
// a/ChildWhichExtendsBaseAbstract.java
package a;
public class ChildWhichExtendsBaseAbstract extends BaseAbstract {
}
// a/SomeOtherClassWhichUseGenerics.java
package a;
public class SomeOtherClassWhichUseGenerics<T extends BaseAbstract> {
}
// b/Test.java
package b;
import a.ChildWhichExtendsBaseAbstract;
import a.SomeOtherClassWhichUseGenerics;
public class Test {
public static void main(String[] args) {
/**
* Compile error as BaseAbstract is invisible
*/
SomeOtherClassWhichUseGenerics<BaseAbstract> obj1 =
new SomeOtherClassWhichUseGenerics<BaseAbstract>();
/**
* Compiles correctly
*/
SomeOtherClassWhichUseGenerics<ChildWhichExtendsBaseAbstract> obj2 =
new SomeOtherClassWhichUseGenerics<ChildWhichExtendsBaseAbstract>();
}
}
这种方法的局限性在于您应该在同一个包a
定义所有可能的子类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.