Effektives Java - Gleiche Aufrufzeit für die Methode, obwohl mehrere Instanzen erstellt wurden

Ich lerne Effective Java und in Punkt 5 des Buches spricht Joshua Bloch über die Vermeidung unnötiger Objekte. Ein Beispiel zeigt veränderbare Datumsobjekte, die nach der Berechnung ihrer Werte nie mehr geändert werden.

Hier die "schlechte Praxis":

public Person(Date birthDate) {
    this.birthDate = new Date(birthDate.getTime());
}

// DON'T DO THIS!
public boolean isBabyBoomer() {
    // Unnecessary allocation of expensive object
    Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
    Date boomStart = gmtCal.getTime();
    gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
    Date boomEnd = gmtCal.getTime();
    return birthDate.compareTo(boomStart) >= 0
            && birthDate.compareTo(boomEnd) < 0;
}

Die isBabyBoomer-Methode erstellt unnötigerweise jedes Mal, wenn sie aufgerufen wird, einen neuen Kalender, eine neue Zeitzone und zwei neue Datumsinstanzen - und das ist für mich eindeutig sinnvoll.

Und hier der verbesserte Code:

public Person(Date birthDate) {
    this.birthDate = new Date(birthDate.getTime());
}

/**
 * The starting and ending dates of the baby boom.
 */
private static final Date BOOM_START;
private static final Date BOOM_END;

static {
    Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
    BOOM_START = gmtCal.getTime();
    gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
    BOOM_END = gmtCal.getTime();
}

public boolean isBabyBoomer() {
    return birthDate.compareTo(BOOM_START) >= 0
            && birthDate.compareTo(BOOM_END) < 0;
}

Kalender-, Zeitzonen- und Datumsinstanzen werden bei der Initialisierung nur einmal erstellt. Bloch erklärt, dass dies zu erheblichen Leistungssteigerungen bei der Methode führtisBabyBoomer()wird häufig aufgerufen.

Auf seiner Maschine:
Schlechte Version: 32.000 ms für 10 Millionen Aufrufe
Verbesserte Version: 130 ms für 10 Millionen Aufrufe

Wenn ich jedoch die Beispiele auf meinem System ausführe, ist die Leistung genau gleich (14 ms). Ist das eine Compilerfunktion, bei der die Instanzen nur einmal erstellt werden?

Bearbeiten:
Hier ist meine Benchmark:

    public static void main(String[] args) {
    Calendar cal = Calendar.getInstance();
    cal.set(1960, Calendar.JANUARY, 1, 1, 1, 0);
    Person p = new Person(cal.getTime());
    long startTime = System.nanoTime();
    for (int i = 0; i < 10000000; i++) {
        p.isBabyBoomer();
    }
    long stopTime = System.nanoTime();
    long elapsedTime = stopTime - startTime;
    double mseconds = (double) elapsedTime / 1000000.0;
    System.out.println(mseconds);
}

Prost, Markus

Antworten auf die Frage(2)

Ihre Antwort auf die Frage