Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.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_Inheritance_Static_Initialization_Static Initializer - Fatal编程技术网

我能保证Java中静态初始值设定项的运行顺序吗?

我能保证Java中静态初始值设定项的运行顺序吗?,java,inheritance,static,initialization,static-initializer,Java,Inheritance,Static,Initialization,Static Initializer,我有一个集合类(这是J2ME,所以我对标准API的访问有限;只是为了解释我的车轮改造)。我使用set类在类和子类中创建常量集。有点像这样 class ParentClass { protected final static Set THE_SET = new Set() {{ add("one"); add("two"); add("three"); }}; } class SubClass extends ParentClas

我有一个集合类(这是J2ME,所以我对标准API的访问有限;只是为了解释我的车轮改造)。我使用set类在类和子类中创建常量集。有点像这样

class ParentClass
{
    protected final static Set THE_SET = new Set() {{
        add("one");
        add("two");
        add("three");
    }};
}


class SubClass extends ParentClass
{
    protected final static Set THE_SET = new Set() {{
        add("four");
        add("five");
        add("six");
        union(ParentClass.THE_SET); /* [1] */
    }};
}
除了[1]处的行导致空指针异常外,所有操作看起来都正常。这可能意味着子类中的静态初始化器在父类的静态初始化器之前运行。这让我很惊讶,因为我原以为它会先在任何新导入中运行静态块,然后再在instatiated子类中运行任何静态块

我的假设正确吗?有没有办法控制或解决这种行为

更新:

事情就更奇怪了。我尝试了这个方法(注意“newparentclass()”行):

输出很奇怪:

a
["one", "two", "three"]
b
c
d
e
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException

因此父类是初始化的,但子类在其静态初始值设定项中无权访问它。

不能保证类之间的静态初始值设定项顺序。在类中,它们按照源代码的顺序运行


如果你仔细想想,它们真的不可能是类之间的顺序,因为你也不能控制类的加载时间;您可能会动态加载一个类,或者JVM可能会优化加载顺序。

即使没有
扩展父类
,使用
父类
也会使其初始化

事情变得棘手的地方是当你有周期的时候。使用循环可以在类完全初始化之前访问它。由于Java是一个多线程系统,您还可能遇到死锁和争用问题

可能您的javame实现有缺陷(并非闻所未闻)。完整的
ParentClass
部分引用您的
ChildClass
。或者可能存在其他一些应用程序/库错误

另一方面,如果您没有
-target 1.4
或更高版本,内部类的外部类不会像您预期的那样尽快初始化。如前所述,您的代码在静态上下文中使用(技术上)内部类,所以这不应该是一个问题


另外,有意思的是,在这样的情况下,静态初始化有点混乱,因为实际上有四个类。

这就是您想要实现的吗?或者您是否需要Set接口的本地实现

class ParentClass
{
    protected final static Set THE_SET;

    static {
        THE_SET = new HashSet();
        THE_SET.add("one");
        THE_SET.add("two");
        THE_SET.add("three");
    }
}


class SubClass extends ParentClass
{
    protected final static Set THE_SECOND_SET;

    static {
        THE_SECOND_SET = new HashSet();
        THE_SECOND_SET.add("four");
        THE_SECOND_SET.add("five");
        THE_SECOND_SET.add("six");
        union(ParentClass.THE_SET); /* [1] */
    }
}
考虑到输出行[“一”、“二”、“三”],ParentClass.the_集合基本上不可能从未初始化过


当然,可能不仅仅涉及一个类加载器,但是查看空指针出现的方法和行号肯定会有帮助。

只要停止滥用匿名类的概念进行实例初始化(所谓的“双括号习惯用法”)

我认为Java拼图书或谷歌的YouTube视频中也写了类似的关于Java技巧的内容。

如果A类扩展了B类,B类加载之前,A类难道不需要完全加载吗?我本以为会是另一种情况。当然,A依赖于B的存在,所以B应该先初始化。但是为了得到(或了解B),它必须先通过A中的代码。我认为,这意味着A静态块代码将在B中的代码之前出现。我不知道类文件是什么样子。。我原以为编译器会先列出导入。你们都遇到了问题。首先,实际上,不,编译时的类声明提供了足够的信息来了解方法等。JVM所要做的就是确保在派生类代码调用基类代码时加载该类。可以想象,它可以被构建成一个静态块来强制依赖类的静态块被初始化,但实际上并不是这样。。我想以利亚说得对。这不是初始化顺序的问题,而是一种名称冲突。真正的代码在“C”中是这样的。。。它以一个add(SOME_CONST)开始,该add位于代码中的set之后,因此SOME_CONST为null。似乎命名解决方案就是我想要的答案:)J2ME不允许自定义类加载器。。它相当原始。此外,输出中缺少“f”意味着错误发生在它前面的union()行上。。我不知道它实际上是一个匿名类。这就是我讨厌人们称它为“习语”并给它取个名字的最大原因——它使它听起来像是语言的一个单独的特征,并掩盖了实际发生的事情。
class ParentClass
{
    protected final static Set THE_SET;

    static {
        THE_SET = new HashSet();
        THE_SET.add("one");
        THE_SET.add("two");
        THE_SET.add("three");
    }
}


class SubClass extends ParentClass
{
    protected final static Set THE_SECOND_SET;

    static {
        THE_SECOND_SET = new HashSet();
        THE_SECOND_SET.add("four");
        THE_SECOND_SET.add("five");
        THE_SECOND_SET.add("six");
        union(ParentClass.THE_SET); /* [1] */
    }
}