我希望能够在运行时设置我想要实例化的项目类型。下面是我想要做的简化示例,因为功能不是我问题中最相关的部分(如果您输入Administrable
的子类,它已经正常工作。)
public class Role {
private Class<? extends Administrable> admin;
public Class<? extends Administrable> getAdmin() {
return admin;
}
public void setAdmin(Class<? extends Administrable> admin) {
this.admin = admin;
}
public Administrable getAdministrable() throws InstantiationException, IllegalAccessException {
return admin.newInstance();
}
}
我正在尝试让下面的测试失败并使用ClassCastException
(或任何其他Exception
,但实际上),但我对我的测试代码编译并且在没有抛出任何{{ {1}}。
RuntimeException
这意味着我没有明确检查setter中的原始类型,我真的想要一个。是否可以实施此检查,如果是,如何执行?我尝试了一些反射技术来查看public class RoleTest {
// this works already
@Test
public void testAdmin() {
// Site is a subclass of Administrable
Class<? extends Administrable> clazz = Site.class;
role.setAdmin(clazz);
assertEquals(clazz, role.getAdmin());
}
// this works already
@Test
public void testAdminNull() {
role.setAdmin(null);
assertNull(role.getAdmin());
}
// this test succeeds, i.e. it does not throw any exception
@Test(expectedExceptions = RuntimeException.class) // using TestNG
public void testAdminIllegal() {
Class clazz = String.class;
// I thought that this wouldn't even compile
role.setAdmin(clazz);
// But the strangest thing is that it seems to work at runtime, too !
assertEquals(clazz, role.getAdmin());
}
}
是clazz
是否为ParameterizedType
,还有铸造等,但似乎没有任何工作可以令人满意。
答案 0 :(得分:2)
传递原始类型Class
:
Class clazz = String.class;
// I thought that this wouldn't even compile
role.setAdmin(clazz);
不会抛出任何异常,但您的编译器会警告您使用未经检查的类型。如果你实际上给了一个泛型类Class<?>
,它就不会编译。
要检查作为参数传递的类型,请按如下所示更改方法:
public void setAdmin(Class<? extends Administrable> admin) {
if (admin != null && !Administrable.class.isAssignableFrom(admin)) {
throw new IllegalArgumentException("The parameter " + admin.getName() + " should be administrable.");
}
this.admin = admin;
}
或者,如果您想让测试失败(没有检查),请在管理实例上从Administrable
调用方法:
class Administrable {
public void test(){}
}
public void testAdminIllegal() throws IllegalAccessException, InstantiationException {
Class clazz = String.class;
// I thought that this wouldn't even compile
role.setAdmin(clazz);
role.getAdministrable().test();
}