2017-08-09 135 views
0

我想了解一个类加载并初始化时的确切场景。我看到下面的两篇文章给出不同的答案类加载和初始化

javarevisited - A类类是用在Java中创建whenan实例的初始化无论()关键字或使用反射使用Class.forName(),这可能抛出Java中的ClassNotFoundException。

Java world-那么,什么时候分类加载?有两种情况:执行新的字节码时(例如,FooClass f = 新的 FooClass();)以及字节码对类(例如System.out)进行静态引用时的情况。

所以当我使用new关键字创建一个类的实例是类加载或初始化?


另一件事要问关于装载由于引用变量:

javarevisited - 类加载是由类加载器中的Java可以实现尽快急切地加载类为其他类引用完成,或延迟加载类,直到需要类的初始化发生

是什么笔者通过参考这里是什么意思?他是否暗示如果A类具有B类的引用变量,那么B类在其引用在A中遇到时会被加载?

但笔者下面说类NOTUSED不加载,但我看到有ClassInitializationTest类的参考

javarevisited -

/** * 这是不是在这个程序中使用的Java类,因此不是由JVM */

class NotUsed { 
static { System.out.println("NotUsed Class is initialized "); } 

}

加载3210
+0

通过阅读文章,javaworld文章更加简单化,并提供了高层次的概述,而javarevisited文章更多地涉及细节,因此它们不完全相互矛盾,只是谈论不同的事情。至于你的参考问题,是的,这就是它的意思。 – Oleg

回答

1

你对javaworld文章感到困惑。虽然这有点苛刻,但为了这个答案的目的,我们只是说它是错误的,而忽略它。

jvm specification

Java虚拟机动态加载,链接和初始化类和接口。 加载是找到具有特定名称的类或接口类型的二进制表示并从该二进制表示创建类或接口的过程。链接是取类或接口并将其组合到Java虚拟机的运行时状态以使其可以执行的过程。 初始化类或接口包括执行类或接口的初始化方法

从高亮显示的文本上面可以看到什么加载和初始化意味着和和javaworld使用装载(错误地)作为他们的综合条款。

jls

12.4.1。当初始化时发生

类或接口类型T将在以下中的任何一个的所述第一发生之前​​立即初始化:

  • T是一个类并且创建T的实例。
  • 调用由T声明的静态方法。
  • 指定由T声明的静态字段。
  • 使用由T声明的静态字段,该字段不是常量变量(§4.12.4)。
  • T是顶级类(第7.6节),执行了在T(§8.1.3)中词汇嵌套的断言语句(第14.10节)。

从javarevisited文章:

NotUsed o = null; 
.. 
class NotUsed { 
    static { System.out.println("NotUsed Class is initialized"); } 
} 

声明一个变量没有列为导致初始化,所以它没有初始化的"NotUsed Class is initialized"不会被打印出来的事情之一。如果NotUsed将被加载,使用sun的java 8上的默认ClassLoader它不会被加载,所以它不是由规范定义的。

+0

谢谢@Oleg。作者说:“类加载是通过Java中的类加载器来完成的,一旦另一个类引用它就可以实现加载类,但后来在NotUsed方法的注释中看到”/ ** * Java类,它是未在此程序中使用,因此未由JVM加载* /“但有 ”NotUsed o = null;“ ClassInitializationTest类中的引用语句 –

+0

只是一个简单的例子:考虑我们引用Fizz类。哪个语句导致类加载。我相信(2)会导致Fizz类的使用(加载后)。但是声明(1)是否会导致类加载?Fizz fizz = null; ------------(1) fizz = new Fizz(); ----------(2)。 –

+1

@SreemanthJasti他的意思是规范没有定义要做什么,它可以以任何方式实现。我只是检查了标准的Java 8,他是正确的,它不会被加载。你可以基于[这个答案](https://stackoverflow.com/a/482909/1398418)自己玩。在你的例子中(1)什么都不会发生,但理论上它可以被加载但是不会被初始化(jls禁止它)。 (2)实际上,默认的类加载器会被加载并初始化,理论上它可能已经被加载过。 – Oleg

-1
myClass a = new myClass(); 

正如我所教导的,第一部分是初始化,第二部分是“=”后的加载。

您可以初始化类:

myClass a; 

然后在后面的代码上加载:

a = new myClass(); 

同为变量初始化。

+0

这是不相关的,他问** **类**加载。正如类加载器所做的一样。 – Oleg