2016-11-16 88 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通常是第一种内联方法,因为它们的使用频率很高),所以似乎值得在这里放下额外的注释。 –