繁体   English   中英

在非静态内部类中使用泛型

[英]Using generics in non-static inner class

public abstract class OuterClass<OT extends OuterClass<OT>> {
    public <C extends OuterClass<?>> C parse(Class<C> clazz) {
        if (clazz.isInstance(this)) {
            return (C) this;
        }

        return null;
    }

    public abstract class InnerClass<CT extends InnerClass<CT> {
        public <C extends InnerClass<?>> C parse(Class<C> clazz) {
            if (clazz.isInstance(this)) {
                return (C) this;
            }

            return null;
        }
    }
}

OuterClass<?> oInstance;
InnerClass<?> iInstance;

在上面的示例中, iInstance变量可以正常工作。 但是,在添加泛型部分时, iInstance变量显示错误

在原始类型上给出的类型参数

如果我从变量中删除泛型部分,则以下测试用例将因类型错误而失败

public class ExtendedOuter extends OuterClass<ExtendedOuter> {

}

// This only works on OuterClass<?> and not on OuterClass
ExtendedOuter eInstance = oInstance.parse(ExtendedOuter.class);

找到:OuterClass,必需:ExtendedOuter

在静态/外部类上这没问题,因为它们可以定义为ClassName<?> ,但是非静态内部类不能使用<?>定义<?>

如何在不使InnerClass静态的情况下将<?>添加到iInstance

编辑:让我举一些例子,为什么这些类将其扩展版本用作泛型。

public abstract class OuterClass<OT extends OuterClass<OT>> {
    public abstract OT returnMe();
}

public class ExtendedOuter extends OuterClass<ExtendedOuter> {
    @Override
    public ExtendedOuter returnMe() {
        return this;
    }
}

如果仅在抽象版本上设置返回类型OuterClass ,则上面的示例将不起作用。 如果是这样,则每当使用此方法时都必须转换任何扩展版本,这并不是理想的选择。

在删除<CT> <T extends OuterClass<CT>> <CT>之后,AndroidStudio也出现了错误

参数OT不在其范围内

执行ClassName extends OuterClass<ClassName>时,扩展类中会显示此错误。 换句话说,仅在抽象类上使用<T extends OuterClass>不能正常工作。

与我之前的文章类似,该文章展示了一个构建器模式,该模式使用泛型类型和继承来减少继承情况下的实际代码,对于非静态类也可以这样做。 因此,我相应地修改了构建器示例,以避免生成静态内部类:

带有父构建器的父类:

public abstract class TestParam<Z>
{
    public abstract class CommonBuilder<T extends CommonBuilder<T>>
    {
        protected final String a;
        protected final String b;
        protected final String c;
        protected Z z = null;

        public CommonBuilder(String a, String b, String c) 
        {
            this.a = a;
            this.b = b;
            this.c = c;
        }

        @SuppressWarnings("unchecked")
        public T withOptionalZ(Z z)
        {
            this.z = z;
            return (T)this;
        }

        @SuppressWarnings("hiding")
        public abstract <T> T build();
    }

    protected String name;
    protected String a;
    protected String b;
    protected String c;
    protected Z z = null;

    protected TestParam() {

    }

    protected TestParam(String name, String a, String b, String c)
    {
        this.name = name;
        this.a = a;
        this.b = b;
        this.c = c;
    }

    protected TestParam(String name, String a, String b, String c, Z z)
    {
        this.name = name;
        this.a = a;
        this.b = b;
        this.c = c;
        this.z = z;
    }

    public String getA() 
    {
        return a;
    }

    public String getB()
    {
        return b;
    }

    public String getC()
    {
        return c;
    }

    protected abstract String getContent();

    @Override
    public String toString()
    {
        return name+"[A: " + a + ", B: " + b + ", C: " + c + (z != null ? ", Z: " + z.toString() : "") + getContent() +"]";
    }
}

具有非静态生成器的子类如下所示:

@SuppressWarnings({"hiding", "unchecked"})
public class TestParamA<D,E,Z> extends TestParam<Z>
{
    public class Builder<T extends TestParamA<D,E,Z>, 
                         B extends TestParamA<D,E,Z>.Builder<? extends TestParamA<D,E,Z>, ? extends B, D, E>, 
                         D,E> 
                 extends TestParam<Z>.CommonBuilder<Builder<TestParamA<D,E,Z>,B, D,E>>
    {
        protected D d;
        protected E e;

        public Builder(String a, String b, String c)
        {
            super(a, b, c);
        }

        public B withD(D d)
        {
            this.d = d;
            return (B)this;
        }

        public B withE(E e)
        {
            this.e = e;
            return (B)this;
        }

        @Override
        public <T> T build()
        {
            TestParamA<D,E,Z> t = new TestParamA<>("TestParamA", a, b, c, z, d, e);
            return (T)t;
        }        
    }

    protected D d;
    protected E e;

    public TestParamA() {
        super();
    }

    protected TestParamA(String name, String a, String b, String c, Z z, D d, E e)
    {
        super(name, a, b, c, z);
        this.d = d;
        this.e = e;
    }

    public D getD()
    {
        return d;
    }

    public E getE()
    {
        return e;
    }

    @Override
    protected String getContent()
    {
        return ", D: " + d + ", E: " + e;
    }
}

要测试此外部/内部类的功能,可以实现如下所示:

public class Main
{
    public static void main(String ... args)
    {
        TestParamA<D,E,String> a = new TestParamA<>().new Builder<>("a","b","c").withD(new D()).withE(new E()).build();
        TestParamB<F,G,String> b = new TestParamB<>().new Builder<>("a","b","c").withF(new F()).withG(new G()).withOptionalZ("z").build();
        TestParam<String> c = new TestParamA<>().new Builder<>("a","b","c").withD(new D()).withE(new E()).withOptionalZ("z").build();
        TestParam<?> d = new TestParamB<>().new Builder<>("a","b","c").withF(new F()).withG(new G()).build();

        test(a);
        test(b);
        test(c);
        test(d);

        TestParam<?>.CommonBuilder<? extends TestParam<?>.CommonBuilder<?>> builder = 
            new TestParamA<>().new Builder<>("a", "b", "c").withD(new D()).withE(new E());
        test(builder);
        // or a bit shorter
        TestParam<?>.CommonBuilder<?> builder2 = 
            new TestParamB<>().new Builder<>("a", "b", "c").withF(new F()).withG(new G());
        test(builder2);
    }

    public static void test(TestParamA<?,?,?> testParam)
    {
        System.out.println("Test for ParamA: " + testParam.toString());
    }

    public static void test(TestParamB<?,?,?> testParam)
    {
        System.out.println("Test for ParamB: " + testParam.toString());
    }

    public static void test(TestParam<?> testParam)
    {
        System.out.println("Test for Param: " + testParam.toString());
    }

    public static void test(TestParam<?>.CommonBuilder<?> builder)
    {
        System.out.println("Test for CommonBuilder: " + builder.build().toString());
    }
}

TestParamB是相同的TestParamA -它仅包含varialbe和助洗剂的方法进行FG代替DE 此外, DEFG只是具有简单toString()实现的类,该类仅返回简单的类名。

这将打印以下输出:

Test for ParamA: TestParamA[A: a, B: b, C: c, D: D, E: E]
Test for ParamB: TestParamB[A: a, B: b, C: c, Z: z, F: F, G: G]
Test for Param: TestParamA[A: a, B: b, C: c, Z: z, D: D, E: E]
Test for Param: TestParamB[A: a, B: b, C: c, F: F, G: G]
Test for CommonBuilder: TestParamA[A: a, B: b, C: c, D: D, E: E]
Test for CommonBuilder: TestParamB[A: a, B: b, C: c, F: F, G: G]

但是,在添加泛型部分时,iInstance变量显示错误

在原始类型上给出的类型参数

首先,这不是您应该遇到的问题,因为InnerClass没有在范围内定义。 作为内部类,它的作用域在外部类的作用域之内。 因此,当它在外部类之外时,您需要明确地用外部类对其进行限定,否则它将给您InnerClass符号未找到错误。 因此,您没有显示真正的代码(也许您在某个地方有另一个InnerClass )或没有显示真正的错误。

如果我从变量中删除泛型部分,则以下测试用例将因类型错误而失败

当您使用原始类型访问成员时,将关闭这些成员上的所有泛型。 所以.parse()被擦除到public OuterClass parse(Class clazz) (即使这是真的CT未使用的方法),这就是为什么oInstance.parse(ExtendedOuter.class)返回一个类型OuterClass这是不兼容ExtendedOuter

如何在不使InnerClass静态的情况下将<?>添加到iInstance?

OuterClass<?>.InnerClass<?>OuterClass<Something>.InnerClass<SomethingElse>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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