如何将通配符(?)转换为泛型类型T?
我有我想要使用加载类,并在运行时实例化我的对象的静态方法,但是当我编译,我得到这样的警告:如何将通配符(?)转换为泛型类型T?
warning: [unchecked] unchecked cast
T t = (T) ctor.newInstance();
required: T
found: CAP#1
where T is a type-variable:
T extends Object declared in method <T>forName(String,Set<String>)
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 warning
下面的代码:
public static <T> Set<T> forName(String modulePath, Set<String> classes) throws InvalidModuleException{
try {
ClassLoader cl = new URLClassLoader(new URL[]{new URL(modulePath)});
Set<T> list = new HashSet<>(classes.size());
for (String className : classes) {
Class<?> clazz = (Class<?>) Class.forName(className, true, cl);
Constructor<?> ctor = clazz.getConstructor();
T t = (T) ctor.newInstance();
list.add(t);
}
return list;
} catch (MalformedURLException | ReflectiveOperationException ex) {
throw new InvalidModuleException(ex.getMessage());
}
}
有人可以解释我吗?
[更新] 这里是和实例方法调用:
HashSet<String> set = new HashSet<>();
h.add("fully_classfied_classname_readed_from_file"); //Class that extends AbstractApplication
Set<AbstractApplication> abs = Apps.forName("plugins/module.jar", set);
有一个缺失的位。首先,您尝试将每个对象的类型设置为T
。如果你知道T
prehand,我没有看到你需要通过一组字符串当一个类的对象会做
假设,如果你仍然需要在子类的可能性的情况下谁的理由:
public static <T> Set<? extends T> forName(String modulePath, Set<String> classes, Class<T> claz) throws InvalidModuleException{
try {
ClassLoader cl = new URLClassLoader(new URL[]{new URL(modulePath)});
Set<T> list = new HashSet<>(classes.size());
for (String className : classes) {
Class<?> clazz = Class.forName(className, true, cl);
Constructor<?> ctor = clazz.getConstructor();
Object obj = ctor.newInstance();
list.add(claz.cast(obj));
}
return list;
} catch (MalformedURLException | ReflectiveOperationException | ClassCastException ex) {
throw new InvalidModuleException(ex.getMessage());
}
}
使用字符串来表示的类可以这样做,在一个安全的方式。首先,编译器没有办法知道这组字符串实际上包含完全合格的类名;即使它们是类名称,也不能保证名称指定的类是T
的子类。
不是传递在一组字符串中,通过在一组类,限制为的T
子类:
Set<Class<? extends T>> classes
然后,你可以遍历这些类,并删除任何铸件的需要:
for (Class<? extends T> clazz : classes) {
Constructor<? extends T> ctor = clazz.getConstructor();
T t = ctor.newInstance();
list.add(t);
}
如果推迟类的初始化的要求是绝对的,你别无选择,只能适当地添加@SuppressWarnings
这种方法,并希望从这些字符串加载的配置为c orrect。
我使用Set
@ehbarbian请参考最后一句。从类型的角度来看,你正在做一些本质上不安全的事情。 –
这就是我想要的。加载子类(请参阅更新)。我想你的代码可以帮助。 – ehbarbian
或者,您可以事先更改类的类型Class extends T> clazz = Class.forName(...)。asSubclass(claz);' – newacct