Java - 嵌套级别对象分配
Java - Nested Level object assignment
我目前正在处理很多嵌套关卡对象,并且正在考虑性能问题。
假设我有以下 classes:
class Address {
private String doorNumber;
private String street;
...
}
和另一个 class 客户。
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()
}
我知道访问地址的第一行代码不是干净的代码,我原以为编译器会解决这个问题,但事实并非如此。因为当我反编译我的代码时,我得到了完全相同的东西,所以我不确定编译器是否在那里进行了任何优化。所以我的第一个问题是为什么编译器不清理它并将它分配给一个临时变量?
我的下一个问题是,这与性能有关吗?除了第一个不是非常干净的代码之外,哪个是两者中性能最佳的代码。这是否意味着我的第二组代码行会在编译期间在内部转换为第一组代码?
最后一个,在 class 上调用变量是否比 getter 方法更优化?我只是在考虑性能而没有干净的编码。
副作用。
考虑这种情况,调用 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 字段;很可能来自其他线程。
我目前正在处理很多嵌套关卡对象,并且正在考虑性能问题。
假设我有以下 classes:
class Address {
private String doorNumber;
private String street;
...
}
和另一个 class 客户。
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()
}
我知道访问地址的第一行代码不是干净的代码,我原以为编译器会解决这个问题,但事实并非如此。因为当我反编译我的代码时,我得到了完全相同的东西,所以我不确定编译器是否在那里进行了任何优化。所以我的第一个问题是为什么编译器不清理它并将它分配给一个临时变量?
我的下一个问题是,这与性能有关吗?除了第一个不是非常干净的代码之外,哪个是两者中性能最佳的代码。这是否意味着我的第二组代码行会在编译期间在内部转换为第一组代码?
最后一个,在 class 上调用变量是否比 getter 方法更优化?我只是在考虑性能而没有干净的编码。
副作用。
考虑这种情况,调用 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 字段;很可能来自其他线程。