[英]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和助洗剂的方法进行F
和G
代替D
和E
。 此外, D
, E
, F
和G
只是具有简单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.