2016-11-16 72 views
0

我目前正在使用大量的嵌套級別對象,並且正在考慮性能。Java - 嵌套級別對象分配

所以我們可以說,我有以下類別:

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

和其他類客戶。

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

,當我嘗試訪問它象下面這樣:

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() 
} 

我所知道的第一組線訪問地址是不乾淨的代碼,而我認爲,編譯器會排序了這一點,但它沒有。因爲當我反編譯我的代碼時,我得到了完全相同的東西,所以我不確定編譯器是否在那裏進行任何優化。所以我的第一個問題是編譯器爲什麼不清理它並將其分配給一個臨時變量?

而我的下一個問題是,這與性能有關嗎?除了第一個不是非常乾淨的代碼之外,哪一個是這兩個代碼中性能最好的代碼。這是否意味着,我的第二套代碼行將在編譯期間內部翻譯成第一行代碼?

最後最後一個,調用類的變量比它的getter方法更優化嗎?我只是在沒有清晰編碼的情況下考慮性能。

+0

第二個版本性能會更好,尤其是當addressList是LinkedList <>或其他'List <>'其中'get'不是'O(1)'時。 (假設你會比第一個元素挖得更深。) – bradimus

+0

Thanks @bradimus。我的想法是,我必須勤於變量賦值還是Java編譯器要做什麼優化?我不確定。 –

+0

您可以通過基準測試來檢查自己的表現。在循環中運行代碼幾次,然後用'System.nanoTime()'測量時間。 –

回答

5

副作用。

考慮這種情況的,而不是返回一些文字,呼喚你的get方法有一些內在的副作用:

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

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

當然,在這個方法中這樣的副作用,並沒有太大的意義,但是方法調用可能會留下某種形式的遺留效應。

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

其結果,編譯器不能優化多個方法調用到一個 - 它必須假設一個方法調用有副作用。

還值得注意的是,一種方法也可以內聯 - 這是方法的主體複製到呼叫站點,以避免方法調用開銷。這通常只發生在JVM相信這樣的優化是值得的時候;即因爲它被頻繁地調用。但是,它並不會導致callsite被進一步優化 - 它不會觸發某種臨時變量。

怎麼樣領域?他們不能產生副作用......他們可以嗎?

好了,你現在在想這個問題:

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

他們不會產生副作用,但在臨時變量中,編譯器將不會下降,要麼。這是因爲副作用是雙向街道 - 其他一些方法可能會改變addressList字段;最有可能來自其他一些線程。

+0

愛你的答案盧克,現在有很多意義。我不知道爲什麼我沒有從這個角度思考它,我一直在想着獲得者和制定者。 –

+0

是的,當我寫這個問題 –

+0

@VishalJumani沒問題的時候,我更多地考慮了行內替換的問題!我有一種感覺內聯可能正在考慮中(getters/setters通常是第一種內聯方法,因爲它們的使用頻率很高),所以似乎值得在這裏放下額外的註釋。 –