`
shawnccx
  • 浏览: 166796 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

初始化对象,静态属性值不正确

 
阅读更多
问题代码:

class Singleton {
  private static Singleton obj = new Singleton();
  public static int counter1;
  public static int counter2 = 0;
  private Singleton() {
    counter1++;
    counter2++;
  }
  public static Singleton getInstance() {
    return obj;
  }
}
public class MyMain {
public static void main(String[] args) {
   Singleton obj = Singleton.getInstance();
   System.out.println("obj.counter1==" + obj.counter1);
   System.out.println("obj.counter2==" + obj.counter2);
}

}
执行结果是:
obj.counter1==1
obj.counter2==0

你有没有被此结果吓一跳?乍看程序代码,你很可能会认为counter1和counter2的值一定会相等,但执行结果显然不是如此.




因为程序在class constructor内,还未将static field初始化时(这时候,counter1和counter2都是0),就调用instance constructor,而instance constructor竟然还会去更动static field的值,使得counter1和counter2都变成1。然后instance constructor执行完,回到class constructor,再把counter2的值设为0(但是counter1维持不变)。最后的结果:counter1等于1,counter2等于0。




改正程序,方法有三:

-方法一:将singleton field的宣告调到counter1与counter2 field之后。这是最好的作法。
-方法二:将counter2=0的宣告中,「=0」的部分删除。这种作法只有在希望
-方法三:将初始化的动作搬到class constructors内,自行撰写,而不依赖编译器产生。这是最保险的作法。




分享到:
评论

相关推荐

    Java静态初始化块和对象初始化块

    在Java编程语言中,初始化块是程序执行时用于初始化对象或类的重要机制。这里我们将深入探讨两种类型的初始化块:静态初始化块(Static Initializer Block)和对象初始化块(Instance Initializer Block)。这两种...

    对象初始化流程梳理对象初始化流程梳理

    - **父类非静态初始化**:然后,进行父类的实例初始化,这包括执行父类的非静态初始化块(如果存在)以及父类的非静态属性初始化。在`Person`类中,非静态块和非静态属性`b1`、`b2`会按照它们在类中的顺序执行,...

    类继承的初始化顺序类,继承的初始化顺序

    3. **基类非静态成员初始化**:当创建一个子类对象时,会首先调用基类的构造函数来初始化基类的非静态成员变量。 4. **子类非静态成员初始化**:接着是子类的非静态成员变量初始化。 5. **基类构造函数调用**:通过`...

    Velocity初始化过程解析

    2. 初始化一个VelocityContext对象,并向其中添加键值对,这些值将在模板中用于替换占位符。 3. 使用VelocityEngine的getTemplate方法加载模板,并调用merge方法,将Context中的值与Template结合,生成最终输出。 ...

    关于类和对象的进一步讨论

    在深入讨论类和对象之前,我们需要明确一个关键点:初始化对象。 在之前的章节中,我们了解了如何通过成员函数,如`set_time`,来初始化类的成员。通常,我们会使用赋值语句或者从输入流中获取值来设置数据成员。...

    无bug带属性填充包括对象嵌套属性填充与多文件上传及所有标签

    这种嵌套填充通常需要递归处理,确保所有子对象都被正确初始化。 其次,"多文件上传"是Web开发中的一项重要功能。它允许用户一次性上传多个文件,常用于图片、文档或其他大型数据的传输。实现多文件上传通常需要...

    java 对象克隆

    - 对于不可克隆的属性,如`final`字段或静态字段,克隆操作不会复制它们。 - 如果类中包含`transient`字段,序列化和反序列化的方法不会保留这些字段的值。 - 考虑到性能和内存消耗,深克隆通常比浅克隆更昂贵。 ...

    构造函数与静态块的执行顺序

    构造函数是一种特殊的方法,它与类同名,并没有返回类型,其主要任务是在创建对象时初始化对象的属性。构造函数可以被重载,即在同一个类中可以有多个具有不同参数列表的构造函数。 静态块(`static`)是在类定义中...

    Java面向对象(高级)- 类的成员之四:代码块

    这是因为静态代码块随着类的加载而执行,非静态代码块在创建对象时执行,而构造器则用于初始化对象。 通过以上例子,我们可以理解代码块在Java面向对象编程中的重要性,尤其是在初始化阶段。静态代码块适用于类级别...

    C++静态成员函数与静态成员变量小结

    因此,静态数据成员的定义(初始化)不应被放在头文件中。 2. 静态数据成员被类的所有对象所共享,包括该类派生类的对象。即派生类对象与基类对象共享基类的静态数据成员。 3. 静态数据成员可以成为成员函数的可选...

    c++面向对象程序设计语言重点难点复习题及答案.pdf

    错误,静态数据成员的初始化是在全局区中进行的,不需要在定义每个类的对象时进行初始化。 2. 当将一个类S定义为另一个类A的友元类时,类S的所有成员函数都可以直接访问类A的所有成员。 正确,当将一个类S定义为...

    php代码-PHP中静态属性和方法的调用正确的是

    静态属性不会随着类实例的创建而被初始化,它们只有一个全局存储位置,所有实例共享同一个值。声明静态属性的语法如下: ```php class MyClass { static $myStaticProperty = '默认值'; } ``` 在类外部访问静态...

    Java类的加载连接和初始化实例分析

    在Java类中对静态属性指定初始值有两种方式:声明静态属性时指定初始值,使用静态初始化块为静态属性指定初始值。 四、JVM初始化类的步骤 JVM初始化类的步骤可以分为五步:首先,假如这个类还没有被加载和连接,...

    C++ 静态成员的类内初始化详解及实例代码

    在C++编程语言中,静态成员是类的共享属性,不属于任何特定的对象实例,而是所有对象共有的。静态成员的初始化有两种方式:类内初始化(in-class initialization)和类外初始化(out-of-class initialization)。本...

    static静态变量使用@Value注入方式.md

    静态变量在类加载时就已经初始化完毕,而Spring Bean的初始化通常发生在应用程序启动过程中,两者的时间点不同步。因此,直接在静态变量上使用`@Value`会导致注入失败,并且在编译或运行时出现警告或错误信息。 ###...

    zongjiewendang

    3. 静态属性:类似静态字段,静态属性提供了类级别状态的访问,不需创建对象实例。它们的规则与静态字段类似,且同样不能访问非静态成员。 4. 静态事件:事件是对象间的通信机制,静态事件的声明和处理遵循一定的...

    选择题(类与对象).docx

    构造函数是类的特殊成员函数,用于在创建对象时初始化对象的状态。它们没有返回类型,可以有参数,可以被重载。例如,选项2的正确答案是B,显示了构造函数的正确定义。析构函数则是与构造函数相反,当对象生命周期...

Global site tag (gtag.js) - Google Analytics