在java中声明多个参数化类对象

时间:2016-10-12 06:51:50

标签: java generics

我们可以在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>

3 个答案:

答案 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;