如何在Java中使用内部类实例化递归绑定泛型?

2022-09-03 15:47:47

我希望使用具有内部类作为参数的泛型外部类。我期望,我将从基类派生,要么使用它的内部,要么派生内部。在每个级别,我都希望从当前的派生级别开始限制内部类的使用。

不幸的是,我在使用该模式时遇到了各种错误和警告,因此我无法想象如何使用它。

package tests.java;

public class Try_GenericInnerRecursion {

    // base class, consisting of outer and inner parts
    public static class Outer1<E extends Outer1<E>.Inner1> {
        public class Inner1 {
        }

        public void addElement(E e) {
            System.out.println("Added " + e.toString());
        }
    }

    // extending outer, but not inner
    public static class Outer2<E extends Outer1<E>.Inner1> extends Outer1<E>{

    }

    // extending both outer and inner
    public static class Outer3<E extends Outer3<E>.Inner3> extends Outer1<E>{
        public class Inner3 extends Inner1 {
        }
    }

    // extending both outer and inner and stopping extension
    public static class Outer4 extends Outer1<Outer4.Inner4> {
        public class Inner4 extends Outer1<Inner4>.Inner1 {
        }
    }



    // instantiating
    public static void main(String[] args) {

        Outer1<Outer1.Inner1> a1; // WARNING: Outer1.Inner1 is a raw type

        a1 = new Outer1<Outer1.Inner1>(); // WARNING: Outer1.Inner1 is a raw type

        Outer1<?> a2; // OK 

        a2 = new Outer1<?>(); // ERROR: Cannot instantiate the type Outer1<?>

        Outer1<Outer1<?>.Inner1> a3; // ERROR: Bound mismatch: The type Outer1<?>.Inner1 is not a valid substitute for the bounded parameter <E extends Outer1<E>.Inner1> of the type Outer1<E>

    Outer1<? extends Outer1<?>.Inner1> a4; // OK

    a4 = new Outer1<Outer1.Inner1>(); // ERROR: Type mismatch

            Outer2<Outer1.Inner1> b1; // WARNING: Outer1.Inner1 is a raw type

            b1 = new Outer2<Outer1.Inner1>(); // WARNING: Outer1.Inner1 is a raw type

        // and so on
    }

}

如何正确使用此模式?


答案 1

我相信你可以简单地做

    DerivedCorpus1<?>

在通配符捕获期间,它变为

    DerivedCorpus1<x> where x extends Corpus<x>.Element

这是正确界定的。

在你的解释中

    DerivedCorpus1<? extends Corpus<?>.Element>

在通配符捕获期间,它变为

    DerivedCorpus1<x> where x extends Corpus<x>.Element
                        and x extends Corpus<?>.Element

显然,该子句是多余的。extends Corpus<?>.Element


答案 2

Outer1<Outer1.Inner1> a1; // WARNING: Outer1.Inner1 is a raw type

实际上,我得到“类型参数Outer1.Inner1不在类型变量E'的范围内”。

Outer1.Inner1是原始类型,因为 是原始类型。要使用非原始类型,您需要编写 .然而,这也必须反过来延长。为了获得这样的递归,您需要一个命名的递归类型。遗憾的是,由于 是 一个非静态内部类,因此它具有 对 的实例的隐式引用,因此任何扩展它的类也需要具有 的封闭实例。 基本上这样做。Outer1Outer1<something>.Inner1somethingOuter1<something>.Inner1Inner1Outer1Outer1Outer4Inner4

Outer4 a1 = new Outer4(); // compiles fine

a2 = new Outer1<?>(); // ERROR: Cannot instantiate the type Outer1<?>

你永远不能做.new something<?>()

Outer1<Outer1<?>.Inner1> a3; // ERROR: Bound mismatch: The type Outer1<?>.Inner1 is not a valid substitute for the bounded parameter <E extends Outer1<E>.Inner1> of the type Outer1<E>

这是事实。 不是 的子类型 - 反之亦然 - 是 的子类型。这就像 how 不是 的子类型一样;反之亦然。Outer1<?>.Inner1Outer1<E>.Inner1Outer1<E>.Inner1Outer1<?>.Inner1ArrayList<?>ArrayList<String>

Outer1<? extends Outer1<?>.Inner1> a4; // OK

这没关系,因为您在顶层有一个通配符,并且通配符的边界与类型参数的边界相交。其实任何满足原边界的东西,都必须满足这个边界,所以这个边界是无用的,这和上面是一样的。EEOuter1<?> a2;

a4 = new Outer1<Outer1.Inner1>(); // ERROR: Type mismatch

不起作用,原因之一是,除其他原因外,不起作用的原因相同(不满足 的约束)。它还不能满足你的束缚()我相信。a1Outer1.Inner1EOuter1<?>.Inner1

Outer2<Outer1.Inner1> b1; // WARNING: Outer1.Inner1 is a raw type

出于同样的原因,这实际上给出了与 相同的错误。a1


推荐