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

标签 java android generics

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添加泛型部分时变量显示错误

Type arguments given on a raw type

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

public class ExtendedOuter extends OuterClass<ExtendedOuter> {

}

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

Found: OuterClass, required: ExtendedOuter

这对于静态/外部类来说没有问题,因为它们可以定义为 ClassName<?> ,但非静态内部类不能用 <?> 定义

如何添加<?>iInstance不做InnerClass静止的?

编辑: 让我举一些例子,为什么这些类使用它们的扩展版本作为通用类。

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> 后,AndroidStudio 也出现错误在<T extends OuterClass<CT>>

The parameter OT is not within it's bound

执行 ClassName extends OuterClass<ClassName> 时,扩展类中会显示此错误。换句话说,仅使用 <T extends OuterClass> 是行不通的。关于抽象类。

最佳答案

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

具有父构建器的父类:

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());
    }
}

TestParamBTestParamA 相同 - 它仅包含 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]

关于java - 在非静态内部类中使用泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31275493/

相关文章:

java - Android 上的身份验证

java - 避免 Java 中泛型的警告

Java Stream Sort - 具有 2 个或更多对象条件的比较器

java - android studio 加载图像大小的两倍

java - 如何从 JTextField 获取用户输入?

android - 我可以在手机上获取已安装应用程序的 APK 文件吗

java - 使用 Firebase Android API 按嵌套数据排序查询时出现异常

java - 使用有界通配符推断类型的问题

c# - C# 编译器如何区分抽象方法的具体子类实现和抽象基类中的重载?

java - 带有 iText 的 pdfCalligraph 插件支持古吉拉特语