Java检查类是否存在

Java检查类是否存在

对于决定使用哪个接口的实现类,检查类的存在性非常有用。本文我们探索 Class.forName()方法检查类路径下是否存在特定类的一些细节差异。

1. 使用Class.forName()

使用java反射检查类的存在性,对于 Class.forName()方法,其文档中指出如果类不存在则抛出 *ClassNotFoundException*异常。

1.1 检测ClassNotFoundException异常

首先我们写个测试期望抛出ClassNotFoundException异常,这样可以知道测试满足期望:

@Test(expected = ClassNotFoundException.class)
public void givenNonExistingClass_whenUsingForName_thenClassNotFound() throws ClassNotFoundException {
    Class.forName("class.that.does.not.exist");
}

这样我们能够证明当类不存在是会抛 *ClassNotFoundException*异常。让我们写个类测试其确实存在:

@Test
public void givenExistingClass_whenUsingForName_thenNoException() throws ClassNotFoundException {
    Class.forName("java.lang.String");
}

这个测试证明 Class.forName() 方法在类确实存在时不在抛异常。然而这并不是完美的解决方案。

1.2 类初始化的副作用

需要特别指出的是,没有指定类加载器,Class.forName() 方法对执行类的静态初始化代码块,这回导致异常行为。

为了验证这种行为,下面创建一个类在静态块中国抛出 RuntimeException异常,这样可以知道初始化块是否被执行:

public static class InitializingClass {
    static {
        if (true) { //enable throwing of an exception in a static initialization block
            throw new RuntimeException();
        }
    }
}

通过查阅 forName文档,我们看到如果初始化失败会抛出 ExceptionInInitializerError异常。下面写个测试进行验证:

@Test(expected = ExceptionInInitializerError.class)
public void givenInitializingClass_whenUsingForName_thenInitializationError() throws ClassNotFoundException {
    Class.forName("path.to.InitializingClass");
}

执行初始化块有不可见的副作用。现在知道了如何引起性能问题或潜在错误。下面讨论如何跳过类初始化。

2. 跳过 Class.forName() 中初始化

幸运的是,forName()方法提供了重载方法,其接收一个类加载器,以及是否执行类初始化两个参数。根据文档,下面调用时等价的:

Class.forName("Foo")
Class.forName("Foo", true, this.getClass().getClassLoader())

现在我们修改true为false,测试测试进行验证是否触发了静态块的调用:

@Test
public void givenInitializingClass_whenUsingForNameWithoutInitialization_thenNoException() throws ClassNotFoundException {
    Class.forName("path.to.InitializingClass", false, getClass().getClassLoader());
}

3. Java9 实现

对于Java9及以上版本,有第三个重载方法,其接收模块或类名字符串。该重载默认不运行类初始化,另外如果请求的类不存在不再抛异常而是返回null。

4. 总结

本文我们解释了调用Class.forName会引起类初始化的副作用和性能问题,因此尽量使用其重载方法避免这些问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值