访问参数化类型的类型参数

时间:2014-10-07 10:36:46

标签: java generics nested-generics

我有一个参数化类型A<T extends B>,另一个C<T2 extends A>

是否可以(静态地)引用T内的C子类而无需将T添加为C的第二个类型参数?目标是向C添加返回类型为T的方法。

我想写些什么:

class A<T extends B> {

}

class C<T2 extends A<T>> {
    T myMethod() {

    }
}

3 个答案:

答案 0 :(得分:2)

就目前情况而言,您在A的定义中使用C作为原始类型:

C<T2 extends A>

这是一个坏主意,你不能期望在这个上下文中获得有关类型参数的信息,因为你没有指定任何。找不到T

A的定义中,类型T只是一个参数。在您使用特定类作为参数的特定A之前,T不会引用任何内容。当您定义C时,您必须说明您正在扩展的A的含义,换句话说,指定一个真实的类型。

您正在做的有点像询问xf(x) = x+1的价值是什么。在您使用某个特定参数调用f之前,x只是一个标签。

答案 1 :(得分:0)

section 4.4 of the spec

A type variable is introduced by the declaration of a type parameter of
a generic class, interface, method, or constructor.

T right extends的出现是一个类型变量,而不是类型参数。如果要将其用作变量,则它必须是范围中的参数。

您可以添加T作为参数,如下所示:

class A<T extends B> {
    ...
}

class C<T, T2 extends A<T>> {
    T myMethod() {
        ...
    }
}

但这是你的问题试图避免的。另一种方法是使C成为内部类:

class A<T extends B> {

    class C<T2 extends A<T>> {
        T myMethod() {
            ...
        }
    }

    ...
}

答案 2 :(得分:0)

我认为答案是肯定的,你可以间接地。

由于类型擦除,我认为你无法直接做到这一点。 正如其他人所提到的,你必须添加另一个参数,或类型参数,或嵌套类。

您可以使用泛型函数,类的调用者的帮助和基类的帮助来间接地执行此操作:

class B
{

}

class B2 extends B  // B2 is Just an example of a concrete type T 
{

}

class A<T extends B> {
  T t;
  T getT()
  {
      return t;
  }
}

class C<T2 extends A<?>> {
     T2 t2;

     T2 getT2()
     {
         return t2;
     }
     <X> X getValWithInnerType(A<? extends X> x)
     {
        return x.getT();
     }

}



public class Example {

    public static void main(String[] args) {
        C<A<B2>> c1 = new C<>();
        B2 inner = c1.getValWithInnerType(c1.getT2());

    }
}

如果你愿意获得你想要的类型,但不一定直接来自C类,你也可以使用组合做一些更简单的事情:

class B
{

}

class B2 extends B
{

}

class A<T extends B> {
  T t;
  T getT()
  {
      return t;
  }
}

class C<T2 extends A<?>> {
     T2 t2;
     T2 getT2()
     {
         return t2;
     }

}



public class Example {



    public static void main(String[] args) {
        C<A<B2>> c1 = new C<>();
        B2 inner = c1.getT2().getT();

    }
}

最后,如果获得精确的派生类型T并不是那么重要,那么你可以让函数返回类型B:

class B
{

}

class B2 extends B
{

}

class A<T extends B> {
  T t;
  T getT()
  {
      return t;
  }
}

class C<T2 extends A<? extends B>> {
     T2 t2;

     B getT2()
     {
         return t2.getT();
     }


}