繁体   English   中英

如何使用“extends”使用带有排他性的泛型?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM