故事背景 有一天,老鼠小白发现了一个奇怪的问题,它的奶酪的生产日期被谁搞丢了,不知道奶酪是否过期,可怎么吃呀? 谁动了我的奶酪?--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) : 18153 cheese had produces : 18153 days 这是怎么回事呢? 谁动了我的奶酪?--java实例初始化的顺序问题 破案 查看代码提交记录,发现老鼠小蓝有修改记录,仅仅调整了两行程序的顺序,小白原来的代码如下: 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) : 18153 cheese had produces : 13 days 这才是小白鼠想要的结果! 于是小白鼠去请教java的创造者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 Date object and initializes it so that * it represents midnight, local time, at the beginning of the day * specified by the year, month, and * date 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 Calendar.set(year + 1900, month, date) * or GregorianCalendar(year + 1900, month, date). */ @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