谁动了我的奶酪?--java实例初始化的顺序问题

故事背景

有一天,老鼠小白发现了一个奇怪的问题,它的奶酪的生产日期被谁搞丢了,不知道奶酪是否过期,可怎么吃呀?

让我们来看看吧

import java.util.Date;public class Cheese {	public static final Cheese cheese=new Cheese();	private final long produceTimes;	private static final long produceDate =new Date(119,8,1).getTime();

	private Cheese() {		produceTimes=new Date().getTime()-produceDate;	}

	public long produceTimes() {		return produceTimes;	}

	public static void main(String[] args) {		System.out.println("current time in day(from 1900:00:00) : "+new Date().getTime()/(1000*60*60*24L));

		System.out.println("cheese had produces : "+ cheese.produceTimes()/(1000*60*60*24L) +" days");

	}}

按照小白的预期,程序该跑出奶酪上市了多少天,可是打印出的结果确实奶酪不会过期

current time in day(from 1900:00:00) : 18153cheese had produces : 18153 days

这是怎么回事呢?

破案

查看代码提交记录,发现老鼠小蓝有修改记录,仅仅调整了两行程序的顺序,小白原来的代码如下:

import java.util.Date;public class Cheese {

	private final long produceTimes;	private static final long produceDate =new Date(119,8,1).getTime();	public static final Cheese cheese=new Cheese();

	private Cheese() {		produceTimes=new Date().getTime()-produceDate;	}

	public long produceTimes() {		return produceTimes;	}

	public static void main(String[] args) {		System.out.println("current time in day(from 1900:00:00) : "+new Date().getTime()/(1000*60*60*24L));

		System.out.println("cheese had produces : "+ cheese.produceTimes()/(1000*60*60*24L) +" days");

	}}

仅仅修改了两个变量的顺序,输出的结果就大相径庭了

current time in day(from 1900:00:00) : 18153cheese had produces : 13 days

这才是小白鼠想要的结果!

于是小白鼠去请教java的创造者java之父

原来,实例的初始化也是有讲究的。

1.static字段先设置默认值,其中cheese被设置为null,produceDate被设置为0

2.然后static初始器执行,按照声明出现的顺序执行:

如果先执行cheese的话,调用Cheese()构造方法,此时用produceDate=0为值。

如果先执行produceDate的话,producteDate被设置为2019-09-01,再调用cheese()构造方法。

3 最后从构造器返回cheese类的初始化。

说明

Date设置日期为2019-09-01 为何设置为

new Date(119,8,1)

大家可以进去源码看说明情况

 /**
 * Allocates a <code>Date</code> object and initializes it so that
 * it represents midnight, local time, at the beginning of the day
 * specified by the <code>year</code>, <code>month</code>, and
 * <code>date</code> arguments.
 *
 * @param year the year minus 1900.
 * @param month the month between 0-11.
 * @param date the day of the month between 1-31.
 * @see java.util.Calendar
 * @deprecated As of JDK version 1.1,
 * replaced by <code>Calendar.set(year + 1900, month, date)</code>
 * or <code>GregorianCalendar(year + 1900, month, date)</code>.
 */
 @Deprecated
 public Date(int year, int month, int date) {
 this(year, month, date, 0, 0, 0);
 }

其中,year份是从1900年开始的年数,即2019-1900=119

month是0~11计数的,需要实际月份减1,即9-1=8

date 是1~31计数的,实际天就可以 即1

参考资料

【1】https://docs.oracle.com/javase/specs/jls/se12/html/jls-12.html#jls-12.4

原文地址:https://www.cnblogs.com/davidwang456/p/11518296.html

时间: 2024-11-06 03:53:45

谁动了我的奶酪?--java实例初始化的顺序问题的相关文章

Java程序初始化的顺序是怎样的

在Java语言中,当实例化对象时,对象所在类的所有成员变量首先要进行初始化,只有当所有类成员完成初始化后,才会调用对象所在类的构造函数创建对象. Java程序的初始化一般遵循以下三个原则(以下三原则优先级依次递减):(1)静态对象(变量)优先于非静态对象(变量)初始化,其中,静态对象(变量)只初始化一次,而非静态对象(变量)可能会初始化多次.(2)父类优先于子类进行初始化.(3)按照成员变量定义顺序进行初始化.即使变量定义散布于方法定义之中,它们依然在任何方法(包括构造函数)被调用之前先初始化.

Java类、实例初始化的顺序

求如下 java 代码的输出?? class T implements Cloneable{ public static int k = 0; public static T t1 = new T("t1"); public static T t2 = new T("t2"); public static int i = print("i"); public static int n = 99; public int j = print(&quo

【Simple Java】什么是Java实例初始化块

在本篇文章,我将会使用一个例子展示什么是实例变量初始化块,实例初始化块和静态初始化块,然后说明在Java中实例初始化块是如何工作的. 执行顺序 查看下面的代码,你知道哪个先执行吗? package simplejava; class Foo { // instance variable initializer String s = "abc"; // constructor public Foo() { System.out.println("constructor call

Java中初始化的顺序问题小结

以下内容有一部分是自己的总结,还有一部分是借鉴别人的总结. 一.基础概念: 1.构造方法: 构造方法用于执行类的实例初始化工作 ,构造方法又称构造函数.创建对象时,根据传入的参数列表,将自动调用相应的构造方法.  每个类都有构造方法,如果没有显示声明构造方法,编译器会自动生成一个默认的无参数的构造方法.默认构造方法实例化对象,并将未赋值的字段赋予默认值. 注意:如果声明了带有参数的构造方法,编译器则不会自动生成默认的无参数的构造方法,此时如果需要无参数的构造方法,则需要显示声明. 2.初始化代码

java程序初始化的顺序

来自:http://blog.csdn.net/socoolfj/article/details/750425   http://www.cnblogs.com/miniwiki/archive/2011/03/25/1995615.html 规则1(无继承情况下):对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器 规则2(有继承情况下):子类的静态变量和静态初始化块的初始化是在父类的变量.初始化块和构造器初始化之

java对象初始化的顺序

Java代码 public class Son extends Father { String value = null;//2 public Son() { super();  //1 System.out.println("Son:  " + value);//3 } public static void main(final String[] args) { new Son(); } } class Father { public Father() { if (this inst

java程序初始化顺序

使用场景:  在java程序中,当实例化对象时,对象的所在类的所有成员变量首先要进行初始化,只有当所有类成员完成初始化后, 才会调用对象所在类的构造函数创建对象. 初始化的原则: (1)静态对象优先于非静态对象初始化,静态对象只能初始化一次,但非静态对象可以初始化多次. (2)超类优先于派生类初始化. (3)按照成员变量定义的顺序来进行初始化,即使变量定义散布于方法定义之中,它们仍然在任何方法(包括构造器)被调用前初始化. package test; /*java程序初始化的顺序:超类静态变量

阿里巴巴面试题--Java对象初始化

转自 http://blog.csdn.net/ysjian_pingcx/article/details/19605335 Java对象初始化 这是一道阿里巴巴的关于Java对象初始化的面试题,堪称经典,代码很简单(编写格式做了些修改),但是需要面试者对Java中对象初始化有一个透彻的认识,那么通过这道面试题,对我有点启发,所以希望在这里分享给大家,希望能给迷惘的初学者一起指引,下面我们直入主题,先看看代码: 1 public class InitializeDemo { 2 private

Java - 35 Java 实例

Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. Java 环境设置实例 Java 实例 – 如何编译一个Java 文件? Java 实例 – Java 如何运行一个编译过的类文件? Java 实例 - 如何执行指定class文件目录(classpath)? Java 实例 – 如何查看当前 Java 运行的版本? Java 字符串 Java 实例 – 字符串比较 Java 实例 - 查找字符串最后一次出现的位置 Java 实例 -