Java white step on the pit record-class execution order

Xiaobai wanted to implement a program to record the cheese production deadline. After the self-test yesterday, it was submitted to the test MM for testing. After the test MM finished testing, it said that there was no problem. Xiaobai only left work. When I tested MM and walked the automatic regression test this morning, I found a bug.

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

Xiaobai pulled down the code of the test environment and debugged, and found that the running result was indeed wrong:

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

Was it dazzled yesterday and the test MM? Impossible! It must be a code issue. Pulled out to see the history commit record, only to find that Xiaofan made changes to the program, and changed the order of the two lines of code. The procedure before exchange is as follows:

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

operation result:

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

This is the result that Xiaobai wants, and it is also the result that the test MM expects to see.

 

Get to the bottom

It turned out that the initialization of the instance is also very particular.

  1. The static field is first set to a default value, where cheese is set to null and produceDate is set to 0;

  2. Then the static initializer is executed in the order in which the declarations appear:
    if cheese is executed first, the Cheese () constructor is called, then produceDate = 0 is used as the value;
    if produceDate is executed first, producteDate is set to 2019-09-01 , And then call the cheese () constructor.

  3. Finally, return the initialization of the cheese class from the constructor.

In addition, I also learned a new trick

Date Set the date to 2019-09-01 Why is it set to:

new Date(119,8,1)

Take a look at the source code:

 /**
 * 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);
 }

Among them, year  is the number of years since 1900, that is, 2019-1900 = 119;

month  is counted from 0 to 11, and the actual month needs to be decremented by 1, ie 9-1 = 8;

The date  is counted from 1 to 31, and the actual day can be 1.

Published 952 original articles · praised 1820 · 890,000 views

Guess you like

Origin blog.csdn.net/Dream_Weave/article/details/105401255