Xiaobai quería implementar un programa para registrar la fecha límite de producción de queso. Después de la autoevaluación de ayer, se sometió a la prueba MM para la prueba. Después de que la prueba MM terminó la prueba, dijo que no había problema. Xiaobai solo dejó el trabajo. Cuando probé MM y realicé la prueba de regresión automática esta mañana, encontré un error.
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 eliminó el código del entorno de prueba y lo depuró, y descubrió que el resultado de ejecución era realmente incorrecto:
current time in day(from 1900:00:00) : 18153
cheese had produces : 18153 days
¿Estaba deslumbrado ayer y la prueba MM? Imposible! Debe ser un problema de código. Se retiró para ver el registro de confirmación del historial, solo para descubrir que Xiaofan realizó cambios en el programa y cambió el orden de las dos líneas de código. El procedimiento antes del intercambio es el siguiente:
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");
}
}
Resultado de la operación:
current time in day(from 1900:00:00) : 18153
cheese had produces : 13 days
Este es el resultado que Xiaobai quiere, y también es el resultado que la prueba MM espera ver.
Llegar al fondo
Resultó que la inicialización de la instancia también es muy particular.
-
El campo estático se establece primero en un valor predeterminado, donde cheese se establece en nulo y produceDate se establece en 0;
-
Luego, el inicializador estático se ejecuta en el orden en que aparecen las declaraciones:
si se ejecuta cheese primero, se llama al constructor Cheese (), luego se usa produceDate = 0 como valor;
si produceDate se ejecuta primero, producteDate se establece en 2019-09-01 , Y luego llame al constructor cheese (). - Finalmente, devuelva la inicialización de la clase cheese del constructor.
Además, también aprendí un nuevo truco.
Fecha Configure la fecha en 2019-09-01 ¿Por qué está configurada en:
nueva Fecha (119,8,1)
Echa un vistazo al código fuente:
/**
* 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);
}
Entre ellos, año es el número de años desde 1900, es decir, 2019-1900 = 119;
el mes se cuenta de 0 a 11, y el mes real necesita ser disminuido en 1, es decir, 9-1 = 8;
La fecha se cuenta del 1 al 31, y el día real puede ser 1.