Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何检查类是否已初始化?_Java_Classloader_Static Initializer - Fatal编程技术网

Java 如何检查类是否已初始化?

Java 如何检查类是否已初始化?,java,classloader,static-initializer,Java,Classloader,Static Initializer,您可能会问,我为什么要这样做?因为我使用的类(来自外部库)在其静态初始值设定项中处理内容,我需要知道是否已经完成了 我查看了ClassLoader,但没有发现任何有用的东西。有什么想法吗?为什么不直接引用类(通过创建引用、创建实例或访问静态成员)?如果类型初始值设定项尚未启动,则会启动该类型初始值设定项,如果启动了,则您仍可以继续。您可以使用ClassLoader.findLoadedClass()方法。如果返回null,则不加载该类。这样,如果尚未加载该类,则不会加载该类 警告:此代码在这里

您可能会问,我为什么要这样做?因为我使用的类(来自外部库)在其静态初始值设定项中处理内容,我需要知道是否已经完成了


我查看了
ClassLoader
,但没有发现任何有用的东西。有什么想法吗?

为什么不直接引用类(通过创建引用、创建实例或访问静态成员)?如果类型初始值设定项尚未启动,则会启动该类型初始值设定项,如果启动了,则您仍可以继续。

您可以使用
ClassLoader.findLoadedClass()
方法。如果返回null,则不加载该类。这样,如果尚未加载该类,则不会加载该类


警告:此代码在这里不起作用,在系统类加载器中,
findLoadedClass()
受到保护,您需要使用自己的类加载器覆盖它

检查同一主题下的链接,以检查是否使用系统类加载器加载了类


非常好的观点来自@unreputable:

“已加载”并不意味着“已初始化”。初始化仅在JLS3$12.4.1定义的精确时刻发生

我引述:

类或接口类型T将在第一次出现以下任一情况之前立即初始化:

  • T是一个类,并且创建了T的一个实例
  • T是一个类,调用由T声明的静态方法
  • 分配了一个由T声明的静态字段
  • 使用由T声明的静态字段,该字段不是常量变量
  • T是一个顶级类,执行嵌套在T中的
    assert
    语句
在类
class
和包
java.lang.reflect
中调用某些反射方法也会导致类或接口初始化。在任何其他情况下,类或接口都不会初始化


资源:

关于同一主题:


您可以让JVM在加载类时使用-verbose标志打印出类。这可能对你有帮助

java -verbose Dummy|head
[Opened C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.Object from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.io.Serializable from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.Comparable from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.CharSequence from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.String from C:\Program Files\Java\jre6\lib\rt.jar]

(顺便说一句,刚刚在Hello World程序上尝试了这个,它加载了309个类!哇)

您可以尝试以下内容:

类c=newclassloader(){Class c=findLoadedClass(className);}.c


它将阻塞,直到类被初始化(由它自己或其他线程初始化)

如果还不太晚的话。。这也应该很好

 Class.forName().newInstance();

newInstance()
创建由该类对象表示的类的新实例。该类被实例化,就像被一个带有空参数列表的新表达式实例化一样。如果尚未初始化该类,则初始化该类

我知道已经很晚了,但我认为这个答案可能有用。如果您不太害怕(并且您被允许)使用
sun.misc.Unsafe
类,那么有一种方法可以做到这一点:方法

sun.misc.Unsafe.shouldBeInitialized(Class)

当且仅当作为参数提供的
已加载但未初始化时返回
true

这不会导致在进行方法调用时加载
字符串
,因为它必须计算
字符串
文本
“java.lang.String”
?嗯,代码根本不起作用,无法在默认类装入器上调用findLoadedClass()。因此,把它当作一个简单的例子。当然,一个简单的例子,但是,如果语句总是评估为<代码>真的< /代码>吗?那么,如果它能工作,那么它将永远是<代码>真的< /代码>(或者因为字串不可理解:在p类)中爆炸。“加载”并不意味着。“已初始化”。初始化只在JLS3$12.4.1定义的精确时刻发生。您的意思是“是否初始化了一个类”。这有很大的区别。感谢您指出。我更改了标题。哪个库?可能有副作用您可以检查(例如,JDBC驱动程序在DriverManager中注册自己)。这是我工作的公司内部使用的一个库。谢谢你的提示,也许我会找到一些东西。因为这个库使用
System.getProperty
读取参数,我需要知道我是否仍然可以更改它们。注意:这只会在有无参数构造函数可用的情况下工作。情况并非总是如此(如果您使用参数定义了一个或多个构造函数,但没有明确定义无参数构造函数)。
 Class.forName().newInstance();
sun.misc.Unsafe.shouldBeInitialized(Class)