我们可以在Java中声明一个方法
public static <T extends ClassTakesA<A>, A extends ClassTakesBC<B, C>, B extends ClassB, C extends ClassC> T MyFunc(Class<T> clazz) {
T obj = null;
try {
obj = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return obj;
}
因此,在编译时或在IDE中,我们已经知道MyFunc()的参数必须以T为界。这很有效,因为
MyFunc(Object.class) // good, gives compile time error as expected
MyFunc(ClassTakesA.class) // good, although need @SuppressWarnings("unchecked")
现在,如果我需要首先将参数声明为MyFunc(),那么如果参数不受T限制,我应该如何声明它以便我可以获得编译时(或在IDE中)错误? e.g。
public static void main(String[] args) {
Class myClass = Object.class;
MyFunc(myClass); // no error at compile time, but failed in runtime
}
试过这个,但错误的语法
Class<T extends ClassTakesA<A>, A extends ClassTakesBC<B, C>, B extends ClassB, C extends ClassC> myClass;
顺便说一下,你如何摆脱@SuppressWarnings(“未选中”)?
建议是使用
Class<ClassTakesA> myClass = ClassTakesA.class;
但我不允许传递
ClassTakesA<ClassZ> classTakesANot = new ClassTakesA<ClassZ>();
Class<ClassTakesA> myClass = classTakesANot.getClass();
MyFunc(myClass);
由于ClassZ
未展开ClassTakesBC<B, C>
答案 0 :(得分:2)
对于方法调用,您应该将其声明为
Class<ClassTakesA> myClass = ClassTakesA.class;
MyFunc(myClass);
通过这种方式,您可以为编译器提供有关myClass的一些信息,以便在编译期间进行检查。
至于警告你无法摆脱它们,因为在运行时不存在泛型,其中类对象存在。
- 添加番石榴TypeToken -
此外,您可以尝试使用Guava的TypeToken来消除警告,但它会在obj = (T)...
中引入另一个警告
public static <T extends ClassTakesA<A>, A extends ClassTakesBC<B, C>, B extends ClassB, C extends ClassC> T foo(TypeToken<T> clazz) {
T obj = null;
try {
obj = (T) clazz.getRawType().newInstance();
System.out.println("1 " + obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return obj;
}
private <T extends ClassTakesA<A>, A extends ClassTakesBC<B, C>, B extends ClassB, C extends ClassC> void test() {
TypeToken<T> typeToken = new TypeToken<T>(ClassTakesA.class) { };
foo(typeToken);
}
答案 1 :(得分:1)
如果你想使用T,A,B,C,你需要将它们添加到类声明中,而不仅仅是方法声明:
public class MyClass <T extends ClassTakesA<A>, A extends ClassTakesBC<B, C>, B extends ClassB, C extends ClassC> {
public T MyFunc(Class<T> clazz) {
T obj = null;
try {
obj = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return obj;
}
}
然后你可以创建一个扩展ClassTakesA的类,即:
public class ExtendsClassTakesA<A> extends ClassTakesA<A>{}
并通过以下方式调用您的函数:
Class<ExtendsClassTakesA> myClass = ExtendsClassTakesA.class;
MyFunc(myClass);
答案 2 :(得分:1)
终于搞定了。事实证明,这是T, A, B, C
到?
的简单替代,例如
Class<? extends ClassTakesA<? extends ClassTakesBC<? extends ClassB, ? extends ClassC>>> myClass;