2016-11-16 7 views
0

Ich arbeite derzeit mit vielen verschachtelten Level-Objekten und dachte über die Leistung nach.Java - Nested Level Objektzuordnung

Also lassen Sie uns sagen, ich habe die folgenden Klassen:

class Address { 
    private String doorNumber; 
    private String street; 
    ... 
} 

und eine andere Klasse Kunden.

class Customer { 
    private List<Address> addressList; 
    private String firstName; 
    ..... 
    ..... 
    ..... 
} 

und wenn ich versuche, darauf zuzugreifen wie unten:

public static void main(String[] str) { 
    Customer customer = new Customer(); 
    // ... and add addresses to this Customer object. 

    // Set 1 
    // And if I then do... 
    customer.getAddressList().get(0).getHouseNumber(); 
    customer.getAddressList().get(0).getStreet(); 

    // OR 
    // Set 2 
    Address address = customer.getAddressList().get(0); 
    address.getHouseNumber(); 
    address.getStreet() 
} 

Ich weiß, dass die erste Gruppe von Linien, die die Adresse zuzugreifen, ist nicht sauber Code, und ich nahm an der Compiler diese Art würde, aber es tut es nicht. Denn wenn ich meinen Code dekompiliere, bekomme ich genau das gleiche zurück, bin also nicht sicher, ob der Compiler dort irgendwelche Optimierungen vornimmt. Also meine erste Frage ist, warum nicht der Compiler dies aufräumt und es einer temporären Variable zuweist?

Und meine nächste Frage ist, hat das etwas mit Leistung zu tun? Und welcher ist der optimalere performante Code der beiden, abgesehen von dem ersten nicht sehr sauberen Code. Bedeutet es, dass meine zweite Codezeile intern während der Kompilierung in die erste Zeile übersetzt wird?

Und schließlich die letzte, ist es optimal Variablen auf eine Klasse als seine Getter-Methode aufzurufen? Ich denke nur hier Leistung ohne saubere Codierung.

+0

Die zweite Version wird besser funktionieren, besonders wenn 'addressList' eine' LinkedList <> 'oder eine andere' List <> 'ist, wobei' get' nicht 'O (1)' ist. (Angenommen, Sie werden tiefer graben als das erste Element.) – bradimus

+0

Danke @bradimus. Die Idee ist, dass ich bei der Variablenzuweisung fleißig sein muss oder macht der Java-Compiler irgendwelche Optimierungen? Bin nicht sicher. –

+0

Sie können die Leistung selbst überprüfen, indem Sie ein Benchmarking durchführen. Führen Sie den Code einige Male in einer Schleife aus und messen Sie die Zeit mit 'System.nanoTime()'. –

Antwort

5

Nebenwirkungen.

Betrachten Sie diesen Fall, wo stattdessen einen Text zurückzukehren, kommen Aufruf der Methode hat einige interne Nebeneffekt:

// This goes up each time getAddressList is called. 
public int addressesRequested; 

public List<Address> getAddressList(){ 
    addressesRequested++; 
    return addressList; 
} 

Natürlich wird bei diesem Verfahren eine solche Nebenwirkung nicht viel Sinn macht, Es gibt jedoch eine Vielzahl von Möglichkeiten, wie ein Methodenaufruf eine Form von Restwirkung hinterlassen kann.

customer.getAddressList(); // addressesRequested is now 1. 
customer.getAddressList(); // addressesRequested is now 2. 
... 

Als Ergebnis der Compiler können nicht mehrere Verfahren optimieren Anrufe in ein - es muss davon ausgehen, dass ein Methodenaufruf Nebenwirkungen hat.

Es ist auch erwähnenswert, dass eine Methode auch inline sein kann - das ist, wo der Körper der Methode in die Aufruf-Site kopiert wird, um eine Methode zu vermeiden, ruft Overhead auf. Dies geschieht in der Regel nur, wenn die JVM eine solche Optimierung für erforderlich hält. weil es häufig aufgerufen wird. Es führt jedoch nicht dazu, dass die Callsite weiter optimiert wird - sie wird dort keine temporäre Variable auslösen.

Was ist mit Feldern? Sie können keine Nebenwirkungen erzeugen ... können sie?

Ok, also Sie denken jetzt darüber nach:

// Assume addressList was public and could be accessed like so: 
customer.addressList.get(0).. 
customer.addressList.get(0).. 
.. 

Sie produzieren keine Nebenwirkungen, aber der Compiler wird es auch nicht in einer temporären Variablen fallen. Dies ist, weil Nebenwirkungen eine Zwei-Wege-Straße sind - eine andere Methode könnte das Feld addressList ändern; wahrscheinlich von einem anderen Thread.

+0

Liebe deine Antwort Luke, das macht jetzt so viel Sinn. Ich weiß nicht, warum ich aus dieser Perspektive nicht darüber nachgedacht habe und ich habe immer wieder an Getter und Setter gedacht. –

+0

Yup, ich dachte mehr an die Linien der Inline-Substitution, als ich die Frage schrieb –

+0

@VishalJumani Kein Problem! Ich hatte das Gefühl, dass Inlining wahrscheinlich in Betracht gezogen wurde (Getter/Setter sind normalerweise die ersten Arten von Methoden, um inline zu werden, weil sie häufig benutzt werden), so dass es sich lohnte, diese zusätzliche Note auch dort hinein fallen zu lassen. –