`
cantellow
  • 浏览: 848366 次
  • 性别: Icon_minigender_1
  • 来自: 草帽海贼团
社区版块
存档分类
最新评论

第二惑:类型在没有被完全初始化之前就生成实例对象所表现的情况

    博客分类:
  • Java
阅读更多
public class MainTest { 
public static void main(String[] args) { 
Singleton obj = Singleton.getInstance(); 
System.out.println("obj.counter1==" + obj.counter1); 
System.out.println("obj.counter2==" + obj.counter2); 
} 
} 

class Singleton { 

public static int counter1; 
public static int counter2 = 0; 
private static Singleton obj = new Singleton(); 
private Singleton() { 
counter1++; 
counter2++; 
} 

public static Singleton getInstance() { 
return obj; 
} 
} 

结果为:

obj.counter1==1
obj.counter2==1

再看:

public class MainTest { 
public static void main(String[] args) { 
Singleton obj = Singleton.getInstance(); 
System.out.println("obj.counter1==" + obj.counter1); 
System.out.println("obj.counter2==" + obj.counter2); 
} 
} 

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; 
} 
} 

 

结果为:

obj.counter1==1
obj.counter2==0

问题:为什么后者的counter2会是0而不是1?

=================================================================================

参考理解:

第一种:

在main函数里调用Singleton 的静态方法时
虚拟机只加载Singleton 类并初始化其中的静态字段,但是并不分配空间创建此类的对象。
public static int counter1;
public static int counter2 = 0;
private static Singleton obj = new Singleton();
执行了静态变量counter1,counter2初始化后,遇到new Singleton() 指令,然后虚拟机又开始检查Singleton 是否被初始化,检查得知没有完全被初始化,虚拟机开始初始化,并调用构造方法生成实例对象,所以在执行counter1++; counter2++; 之前,他们两个的值都是0,执行了counter1++; counter2++; 之后为1,1。

而第二种:
private static Singleton obj = new Singleton();
public static int counter1;
public static int counter2 = 0;
虚拟机执行new Singleton(前面和第一种一样)时,首先也检查Singleton类是否被初始化,发现没有被初始化,所以继续初始化,之后开始分配空间创建对象,并执行counter1++; counter2++; 这个时候counter1和counter2都为1,但是private static Singleton obj = new Singleton(); 语句结束之后,前面初始化此类的方法调用还在继续,所以会继续执行
public static int counter1;
public static int counter2 = 0;
所以,counter2 被重新赋值为0.

1
1
分享到:
评论

相关推荐

    System.Lazy 实例的延迟初始化值

    - **CreateValue()**:这个方法用于强制初始化值,即使之前没有通过`Value`属性访问过。 - **Equals()** 和 **GetHashCode()**:这些方法考虑了`Lazy<T>`实例的值,因此在比较`Lazy<T>`实例时,会基于其包含的值...

    智能小区设备初始化

    在这个项目实例中,我们将深入探讨智能小区设备初始化的过程、技术应用以及相关知识点。 首先,智能小区设备涵盖了诸多方面,包括但不限于门禁系统、监控摄像头、停车场管理系统、能源计量设备、智能家居设备等。...

    Swift 初始化语法糖,更简介的语法实现组件初始化.zip

    在Swift编程语言中,初始化是创建对象的关键步骤,它允许我们为新实例设置初始状态。在Swift中,初始化过程不仅可以遵循传统的初始化语法,还可以利用一些“语法糖”(即简化语法的特性)来使代码更加简洁易读。...

    winform 初始化器源码

    在WinForm应用中,初始化过程通常是程序启动时执行的第一部分代码,它负责设置窗口、控件以及应用的其他关键组件。以下是一些关于WinForm初始化器源码的关键知识点: 1. **主窗体的构造函数**:这是WinForm应用的...

    C# 生成二维码名片 实例源码

    3. 初始化二维码生成器:根据所选库,创建相应的二维码生成对象,并设置参数,如纠错级别、版本等。 4. 设置自定义样式:为了使二维码更具个性化,可以自定义其颜色、边框、大小等属性。 5. 生成二维码图像:将...

    Java编程思想第05章初始化与清理.ppt

    《Java编程思想》第五章主要讨论的是对象的初始化与清理,包括构造器的使用、方法重载以及默认构造器的概念。下面将详细阐述这些知识点。 ### 一、构造器确保初始化 1. **为什么要引入构造器**:在Java中,构造器...

    Java面向对象程序设计(第二版)

    综上所述,《Java面向对象程序设计(第二版)》所涉及的知识点大致涵盖了面向对象编程的核心概念、类与对象、接口与抽象类、包的使用、异常处理机制、集合框架,以及I/O操作等。这些知识点构成了Java编程语言的基础...

    条形码的生成和解码实例

    代码通常会展示如何初始化库,设置条形码类型,编码数据,生成图像,以及如何读取和解码条形码图像。 通过这个实例,开发者不仅可以学习到如何在项目中集成条形码功能,还能了解条形码技术的基本原理。无论是为了...

    VISUAL C++实效编程280例

    第2章 菜单和光标 2.1 实例23:动态添加和删除菜单项 2.2 实例24:在系统菜单中添加和删除菜单项 2.3 实例25:禁用关闭按钮 2.4 实例26:启用和禁用菜单项 2.5 实例27:设置菜单项的检查状态 2.6 实例28:快捷菜单 ...

    Android游戏开发-02初始化环境.WMV

    在Android游戏开发中,环境初始化是开发者迈出的第一步,它为后续的游戏逻辑编写和功能实现奠定了基础。"Android游戏开发-02初始化环境.WMV"这个视频教程很可能详细讲解了如何配置一个完整的Android游戏开发环境。...

    精通hibernate:对象持久化技术孙卫琴第二版part2

    第2章 Java对象持久化技术概述 21 业务数据在内存中表现为实体域对象形式,而在关系数据库中表现为关系数据形式。数据访问代码负责把实体域对象持久化到关系数据库中。 2.1 直接通过JDBC API来持久化实体域对象 21...

    图片上传oss服务器并生成二维码

    1. 使用OSS SDK初始化一个OSSClient实例,传入Access Key ID、Access Key Secret和Bucket的Endpoint。 2. 创建PutObjectRequest对象,指定要上传的本地图片文件路径和在OSS中的目标文件名。 3. 调用OSSClient的...

    精通Hibernate:对象持久化技术第二版part3

    第2章 Java对象持久化技术概述 21 业务数据在内存中表现为实体域对象形式,而在关系数据库中表现为关系数据形式。数据访问代码负责把实体域对象持久化到关系数据库中。 2.1 直接通过JDBC API来持久化实体域对象 21...

    C++对象模型-322

    默认构造函数是在没有参数的情况下可以被调用的构造函数,用于初始化类的对象。如果没有显式定义,默认构造函数会由编译器自动生成。它通常用来为对象的成员变量赋予默认值或进行必要的初始化工作。如果类中包含动态...

    Java面向对象编程思想.pdf

    继承是 Java 面向对象编程的第二大特征,通过类的继承,便于将统一的功能集中在父类中,实现代码的重用和可维护性。继承使得子类可以继承父类的成员变量和方法,从而实现代码的重用和可维护性。 三、多态 多态是 ...

    spring-实例工厂注入

    总结,Spring的实例工厂注入提供了一种灵活的方式来控制对象的创建,尤其是在对象初始化过程复杂或者需要特定处理的情况下。通过自定义工厂类,我们可以将这些细节封装起来,使得Spring容器更专注于管理和协调组件...

    04_传智播客JPA详解_第一个JPA实例与JPA主键生成策略

    【标题】"04_传智播客JPA详解_第一个JPA实例与JPA主键生成策略"涉及的关键知识点主要包括Java Persistence API (JPA)的基础应用、首个JPA实例的创建以及JPA主键生成策略的理解和配置。JPA是Java平台上的一个标准,...

    java源码包---java 源码 大量 实例

     关于数字签名:产生RSA密钥对(myKeyPair),得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥...

    Nhibernate配置生成器

    2. **构造函数**:为方便实例化对象,生成器会创建默认构造函数,有时也会生成带有参数的构造函数,用于初始化对象。 3. **属性访问器(Getters and Setters)**:提供对属性的读写操作,遵循标准的面向对象设计原则...

Global site tag (gtag.js) - Google Analytics