什么会导致Java类被初始化?

时间:2011-08-26 02:05:54

标签: java android classloader

我正在使用Wrapper Class method来允许我处理现有或不存在的课程。使用此技术时,重要的是要知道什么会导致我的Proxy类被初始化。特别是,如果我:

  1. 声明Proxy的实例,而不将其设置为任何内容

    public class myClass {     ...     代理myInst; }

  2. 在永不运行的if语句

    中本地声明Proxy的实例

    public void myMeth {     如果(ProxyIsAvailableWhichItIsNot){         代理myInst;         ...     } }

  3. 更新:正如Henning所指出的,我对初始化类(和静态块运行)的时间感兴趣,而不是在加载时。我更新了问题以反映这一点。

3 个答案:

答案 0 :(得分:2)

如果您使用该URL中列出的技术,则该技术的一部分涉及调用静态方法来验证该类是否可以使用当前API加载。这允许你做这样的事情:

  1. 生成一个布尔值,例如IsMyProxyAvailable
  2. 在代理类
  3. 上调用静态checkAvailable()方法
  4. 方法成功时将值设置为true,否则调用时为false。
  5. 您还可以为此类创建一个处理上述检查的单例工厂,并在可用时返回实例化的类,或者为null。听起来你似乎想要避免必须围绕布尔值,工厂会(有点)使你能够避免(以不同的成本)。

答案 1 :(得分:2)

只要引用它的另一个类已加载,Java实现就可以选择加载类,或者将其推迟到需要初始化类。在第一种情况下,该类可以在加载但不是初始化的情况下(可能永远)坐下很长时间。

相比之下,有一个关于何时初始化(静态初始化程序运行)的类的精确规则,即第一次创建类的对象,或称为静态方法,或非访问-constant静态字段。

阻止JVM尝试加载类的唯一完全可靠的方法是在代码中明确地提及它并使用Class.forName()和反射来请求在某个确定点加载及时,可以抛出和处理ClassNotFoundException。但是,现代JVM通常比语言规范允许的更加懒惰地加载类,因此更乐观的策略通常会在实践中起作用。

链接中描述的“包装器类”技术不能保证可以通过Java工作(参见Java语言规范的第12.1.2节,第3版),但Android / Dalvik完全有可能提供更强大的保证。

答案 2 :(得分:0)

Java有一种非常明确的方式加载类。在Java中,所有代码都通过ClassLoader加载。由类加载的字节在ClassLoader实例的长度内保存在内存中,因此,只要ClassLoader实例存活,您的Class实例就会存在。加载后不能重新加载或重新定义类,而不会丢弃加载它的ClassLoader。当ClassLoader加载一个类时,会调用静态初始化程序块。因此,类加载与类初始化基本相同。

什么触发了要加载的类?如果加载了依赖于它的另一个类。当Java编译器正在编译类时,它会将所依赖的所有限定类名写入类文件。类会尽可能晚地加载,因此通常这意味着在正常条件下实例化它们。但是,拥有静态成员将强制在加载此类之前加载这些成员。当此类实例化时,将加载实例成员。如果您需要有关此过程的大量详细信息,请阅读以下内容:

http://www.ibm.com/developerworks/java/library/j-dyn0429/

幸运的是,Dalvik VM的工作方式与JVM类似,因为Java非常详细地指定了这个过程。

如果Class.forName()成功,在静态初始值设定项中使用Wrapper方法,则定义代理(选项1或2)的方式无关紧要,因为它已经加载。否则父Wrapper类将不会加载。所以只做选项1,因为它更简单。