2016-07-04 28 views
3

Ich bin ein Anfänger bei Java. Ich habe mich gefragt, was in Situationen zu tun ist, in denen eine Variable komplexe Berechnungen erfordert, bevor sie initialisiert werden, aber sobald sie initialisiert sind, wird sie nicht ändern. Ich wollte die Variable final machen, aber anstatt sie im Konstruktor zu initialisieren, würde ich sie lieber in einer Methode initialisieren, damit diese Methode später wiederverwendet werden kann. Gibt es einen Weg, dies zu erreichen?Wie initialisiert man eine letzte Variable, die komplexe Berechnungen erfordert?

Zusätzlich zu allen oben genannten Anforderungen, was passiert, wenn ich den Wert dieser Variablen nur berechnen will, wenn ich es brauche (weil es rechenintensiv ist, es zu berechnen). Was soll ich in solchen Situationen tun?

+3

Sie können immer eine Methode schreiben, die den Wert für die letzte Variable berechnet und die Methode im Konstruktor aufruft, um den Rückgabewert der endgültigen Variablen zuzuweisen. Warum nicht? – SomeDude

+1

Für Ihre zweite Frage übergeben Sie einen booleschen Wert an den Konstruktor des Objekts, 'sheuldInitializeFinalVariable' und abhängig davon, rufen Sie die teure Methode auf, ansonsten default to Parameter less constructor – SomeDude

Antwort

2

Sie können versuchen, den memoize Anbieter von Guava:

Supplier<T> something = Suppliers.memoize(new Supplier<T>() { 
    // heavy computation 
    return result. 
}); 

something.get(); 
something.get(); // second call will return the memoized object. 
+0

Ich frage mich, wie viele andere Entwickler Guava in der täglichen Entwicklung verwenden ? – SomeDude

+0

Es ist eine gute Bibliothek. –

+0

@svasa Wenn du dich für einen Tag entwickelst, ohne Guava zu verwenden, machst du wahrscheinlich etwas falsch. – shmosel

2

Leider können Sie in einem bestimmten Moment keine Variable final machen. Wenn eine Variable final ist, kann (und muss) sie im Konstruktor initialisiert werden.

Sie könnten auch diese (Kredit für folgenden Code npinti) tun:

private boolean isMutable; 
private String someString; 

public void setMutable(boolean value) 
{ 
    this.isMutable = value; 
} 

public void setSomeString(String value) 
{ 
    if (this.isMutable) 
    { 
     this.someString = value; 
    } 
} 
2

Blick mag Sie faule Initialisierung benötigen. Es ist eine Leistungsoptimierung zur Verwendung, wenn ein Ergebnis aus irgendeinem Grund als teuer angesehen wird. Die Ziele sind verzögern eine teure Berechnung, bis es notwendig ist und das Ergebnis dieser teuren Berechnung speichern, so dass die Berechnung nicht wiederholen müssen.

Es folgt ein Beispiel:

public final class Foo { 
    private Data data = null; 

    private Data expensiveComputation() { 
     if(data == null) { // first call to this method 
      Data data = new Data(); 
      // complex computation 
      // store the result to data 
     } else { 
      return data; 
     } 
    } 
} 

Wie Sie nur data initialisiert sehen kann, ist, wenn es gebraucht wird.

Achten Sie darauf, dass ein Problem auftritt, wenn der Code in einer Multi-Thread-Umgebung funktioniert. Dies liegt daran, dass mehrere Threads die Methode gleichzeitig aufrufen können. Um dies zu verhindern können wir ein synchronized Schlüsselwort:

public final class Foo { 
    private volatile Data data = null; 

    private Data expensiveComputation() { 
     if(data == null) { // first call to this method 
      synchronized(Foo.class) { 
       if(data == null) { 
        Data data = new Data(); 
        // complex computation 
        // store the result to data 
       } 
      } 
     } else { 
      return data; 
     } 
    } 
} 

Das synchronized Schlüsselwort nur ein Thread erlauben kann data eingeben und initialisieren.

+0

Das letzte Beispiel funktioniert nicht mit mehreren Threads, es sei denn, Daten werden flüchtig gemacht. –

+0

Danke für die Korrektur meines nachlässigen Fehlers :) – Wilson