Java Generics:显式检查原始类型

时间:2014-10-16 21:27:17

标签: java generics testng

我希望能够在运行时设置我想要实例化的项目类型。下面是我想要做的简化示例,因为功能不是我问题中最相关的部分(如果您输入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,还有铸造等,但似乎没有任何工作可以令人满意。

1 个答案:

答案 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();
}