我目前正在处理很多嵌套级别对象,并且正在考虑性能。
所以我想说我有以下几个类:
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()
}
我知道访问Address的第一组行不是干净的代码,我假设编译器会对此进行排序,但事实并非如此。因为当我对我的代码进行反编译时,我得到完全相同的东西,所以我不确定编译器是否正在进行任何优化。所以我的第一个问题是为什么编译器不清理它并将其分配给临时变量?
我的下一个问题是,这与性能有关吗?除了第一个不是很干净的代码之外,哪个是两者中最优的性能代码。这是否意味着,我的第二组代码行会在编译期间内部转换为第一组代码?
最后是最后一个,在类上调用变量比使用getter方法更优化吗?我只是在考虑没有干净编码的表现。
答案 0 :(得分: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认为这样的优化是值得的时候;即因为它被频繁调用。但是,它不会导致调用点进一步优化 - 它不会在那里触发某种临时变量。
字段怎么样?他们不能产生副作用......他们可以吗?
好的,所以你现在正在考虑这个问题:
// Assume addressList was public and could be accessed like so:
customer.addressList.get(0)..
customer.addressList.get(0)..
..
他们不会产生副作用,但编译器也不会将其放入临时变量中。这是因为副作用是双向的 - 其他一些方法可以改变那个addressList字段;最有可能来自其他一些主题。