考虑到以下场景
class Base { }
class Extended extends Base {}
我可以轻松地在泛型类的构造函数中请求一个类对象,该类对象是泛型类型的某个子类。
class Test<T extends Base> {
Test(Class<? extends T> test) { }
}
这样我就可以执行以下所有操作
new Test<Base>(Base.class);
new Test<Base>(Extended.class);
new Test<Extended>(Base.class); // This is not allowed by the compiler
new Test<Extended>(Extended.class);
这正是我想要的。但是,我无法弄清楚在使用这样的通用方法时如何实现相同的约束:
<T extends Base> void test(T x, Class<? extends T> test) { }
根据此定义,编译器允许执行以下所有操作:
test(new Base(), Base.class);
test(new Base(), Extended.class);
test(new Extended(), Base.class); // even though Base is not a subclass of Extended
test(new Extended, Extended.class);
我认为这是因为类型推断和 Java 确定
<Base>test(new Extended(), Base.class)
而不是
<Extended>test(new Extended(), Base.class)
但是我如何强制执行后一种推理方法?
感谢您的帮助!
对于 future 的读者:在这个问题的第一个版本中,我将 Base
A
和 Extend
B
。我后来澄清了这个符号。然而,这个符号在答案中使用。
最佳答案
这是计算机科学中的一个问题,因此,can be solved by another level of indirection :
<T extends A, U extends T> void test(T x, Class<U> test) {}
在本例中,我们使用一个类型变量(仅限于 A)来捕获对象参数的类型,并使用第二个类型变量(仅限于第一个)来约束类参数的类型。
如果我写出这个示例并将其提供给 javac (1.6.0_26),它会适时地告诉我:
Test.java:14: cannot find symbol
symbol : method test(B,java.lang.Class<A>)
location: class Test<T>
test(b, A.class);
^
1 error
正如 @JohnB 在他的评论中暗示的那样,你可以通过写来解决这个问题:
this.<A, A>test(b, A.class);
或者使用原始类型。
关于java - 捕获方法参数类型并请求相应的类对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17296263/