让我们先来看两个类:Base和Derived类。注意其中的whenAmISet成员变量,和方法preProcess()。

情景1:(子类无构造方法)

class Base {
Base() {
preProcess();
} void preProcess() {
}
} class Derived extends Base {
public String whenAmISet = "set when declared"; void preProcess() {
whenAmISet = "set in preProcess()";
}
} public class StaticTest {
public static void main(String[] args) {
Derived d = new Derived();
System.out.println(d.whenAmISet);
}
}

当.java源代码转换成一个.class文件后,其转换成类似下面的等价代码:

class Base {
Base() {
preProcess();
} void preProcess() {
}
} class Derived extends Base {
public String whenAmISet; {whenAmISet = "set when declared";} void preProcess() {
whenAmISet = "set in preProcess()";
}
} public class StaticTest {
public static void main(String[] args) {
Derived d = new Derived();
System.out.println(d.whenAmISet);
}
}

输出结果是: set when declared

情景2:(子类添加了构造方法)

class Base {
Base() {
preProcess();
} void preProcess() {
}
} class Derived extends Base {
public String whenAmISet = "set when declared"; public Derived() {
whenAmISet = "set in constructor";
} void preProcess() {
whenAmISet = "set in preProcess()";
}
} public class StaticTest {
public static void main(String[] args) {
Derived d = new Derived();
System.out.println(d.whenAmISet);
}
}

当.java源代码转换成一个.class文件后,其转换成类似下面的等价代码:

class Base {
Base() {
preProcess();
} void preProcess() {
}
} class Derived extends Base {
public String whenAmISet; public Derived() {
whenAmISet = "set when declared";
whenAmISet = "set in constructor";
} void preProcess() {
whenAmISet = "set in preProcess()";
}
} public class StaticTest {
public static void main(String[] args) {
Derived d = new Derived();
System.out.println(d.whenAmISet);
}
}

输出结果为:set in constructor

情景3:(赋值的细节)

public class Singleton {

    private static Singleton mInstance = new Singleton();  // 位置1
public static int counter1;
public static int counter2 = 0; private Singleton() {
counter1++;
counter2++;
} public static Singleton getInstantce() {
return mInstance;
} public static void main(String[] args) {
Singleton singleton = Singleton.getInstantce();
System.out.println("counter1: " + singleton.counter1);
System.out.println("counter2: " + singleton.counter2);
}
}

当.java源代码转换成一个.class文件后,其转换成类似下面的等价代码:

public class Singleton {

    private static Singleton mInstance;
public static int counter1;
public static int counter2; static {
mInstance = new Singleton();
counter2 = 0;
} private Singleton() {
counter1++;
counter2++;
} public static Singleton getInstantce() {
return mInstance;
} public static void main(String[] args) {
Singleton singleton = Singleton.getInstantce();
System.out.println("counter1: " + singleton.counter1);
System.out.println("counter2: " + singleton.counter2);
}
}
  • 在Prepare阶段,mInstance、counter1、counter2的初始值为(null,0,0);
  • 执行至 mInstance = new Singleton()时,进行实例创建并调用构造方法,使counter1、counter2变量的值改变为(1,1);
  • 执行counter2 = 0时,counter2的值再次置为0,最终程序的输出结果为:counter1: 1   counter2: 0

同理,以下代码的最终输出结果为:counter1: 1  counter2: 1

public class Singleton {

    public static int counter1;
public static int counter2 = 0;
private static Singleton mInstance = new Singleton(); // 位置2 private Singleton() {
counter1++;
counter2++;
} public static Singleton getInstantce() {
return mInstance;
} public static void main(String[] args) { Singleton singleton = Singleton.getInstantce();
System.out.println("counter1: " + singleton.counter1);
System.out.println("counter2: " + singleton.counter2);
}
}

原因分析:

  1. 陈皓博客
  2. Java Tutor - Visualize Java code execution to learn Java online (also visualize PythonJavaJavaScriptTypeScriptRubyC, and C++ code)

JAVA构造时成员初始化的陷阱的更多相关文章

  1. Java 构造时成员初始化的陷阱

    1.首先列出代码 Base.java public class Base { Base() { preProcess(); } void preProcess() {} } Derived.java ...

  2. Java中的成员初始化顺序和内存分配过程

    Java中的成员初始化顺序和内存分配过程 原帖是这样描述的: http://java.dzone.com/articles/java-object-initialization?utm_source= ...

  3. java类的成员初始化顺序和初始化块知识

    java类的成员初始化顺序和初始化块知识 转自:http://blog.csdn.net/lgfeng218/article/details/7606735 属性.方法.构造方法和自由块都是类中的成员 ...

  4. Java类的成员初始化顺序

    Java类的成员初始化顺序 2017-06-01 代码: public class InitializeSequence { public static void main(String[] args ...

  5. Java继承时的初始化顺序

    Java程序在启动和运行时,需要首先完成初始化的工作.在涉及到继承.static成员变量等因素时,初始化的顺序就复杂起来.下面以一个例子说明继承时的Java初始化顺序. 例子: class Insec ...

  6. Java 类的成员初始化顺序

    做个简单笔录,就当是重温下基础知识. 1.先看代码: package com.test; public class Test { public static void main(String[] ar ...

  7. java 编译时的初始化顺序

    有的时候,java的初始化会对我的工作照成很大影响,所以简单介绍一下, 首先介绍简单的变量的初始化:在类的内部,变量定义的先后顺序决定了初始化的顺序,即使变量定义散布于方法定义之间,它也会先于构造器和 ...

  8. JAVA构造MAP并初始化MAP

    第一种方法:static块初始化 public class Demo{ private static final Map<String, String> myMap; static { m ...

  9. Java类和对象初始化

    类的生命周期: Java类的初始化: 本阶段负责为类变量赋正确的初始值.(类变量即静态变量) Java编译器把所有的类变量初始化语句和静态初始化器通通收集到<clinit>方法中,该方法只 ...

随机推荐

  1. 如何一步一步用DDD设计一个电商网站(七)—— 实现售价上下文

    阅读目录 前言 明确业务细节 建模 实现 结语 一.前言 上一篇我们已经确立的购买上下文和销售上下文的交互方式,传送门在此:http://www.cnblogs.com/Zachary-Fan/p/D ...

  2. Security Policy:行级安全(Row-Level Security)

    行级安全RLS(Row-Level Security)是在数据行级别上控制用户的访问,控制用户只能访问数据库表的特定数据行.断言是逻辑表达式,在SQL Server 2016中,RLS是基于安全断言( ...

  3. 使用CSS3实现一个3D相册

    CSS3系列我已经写过两篇文章,感兴趣的同学可以先看一下CSS3初体验之奇技淫巧,CSS3 3D立方体效果-transform也不过如此 第一篇主要列出了一些常用或经典的CSS3技巧和方法:第二篇是一 ...

  4. iOS系列文章

    本博客全为原创,如果借鉴了其他文章会在博文的下面进行说明.欢迎转载,但要在文章中给出原文链接,谢谢. 有链接的说明已经发布,没有链接的说明还没有发布. 并不是所有的博文都在这里罗列,有兴趣的可以看博客 ...

  5. 如何在ASP.Net创建各种3D图表

    我们都知道,图表在ASP.NET技术中是一种特别受欢迎而又很重要的工具.图表是表示数据的图形,一般含有X和Y两个坐标轴.我们可以用折线,柱状,块状来表示数据.通过图表控件,我们即能表示数据又能比较各种 ...

  6. 玩转spring boot——开篇

    很久没写博客了,而这一转眼就是7年.这段时间并不是我没学习东西,而是园友们的技术提高的非常快,这反而让我不知道该写些什么.我做程序已经有十几年之久了,可以说是彻彻底底的“程序老炮”,至于技术怎么样?我 ...

  7. ASP.NET Aries 3.0发布(附带通用API设计及基本教程介绍)

    主要更新: 1:升级处理机制(js请求由同步变更为异步) 2:优化前端JS:包括API和配置方式. 3:增加InputDialog功能. 4:增远远程验证功能. 5:优化权限安全机制. 6:增加一次请 ...

  8. Memcached简介

    在Web服务开发中,服务端缓存是服务实现中所常常采用的一种提高服务性能的方法.其通过记录某部分计算结果来尝试避免再次执行得到该结果所需要的复杂计算,从而提高了服务的运行效率. 除了能够提高服务的运行效 ...

  9. 正确地编写Objective-C中的便捷方法

    在Objective-C中,如果某个类方法的返回类型就是这个类的实例(例如NSString类中的stringWithFormat:),就可以将这种类方法称为便捷方法(Convenience Metho ...

  10. ABP源码分析三十七:ABP.Web.Api Script Proxy API

    ABP提供Script Proxy WebApi为所有的Dynamic WebApi生成访问这些WebApi的JQuery代理,AngularJs代理以及TypeScriptor代理.这些个代理就是j ...