2016-11-16 5 views
0

В настоящее время я работаю с множеством объектов вложенного уровня и думал о производительности.Java - Назначение объекта вложенного уровня

Так скажем, у меня есть следующие классы:

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

и другого класса Customer.

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

Я знаю, что первый набор линий для доступа к адресу не является чистым кодом, и я предположил, что компилятор будет разобраться в этом, но это не так. Потому что, когда я декомпилирую свой код, я получаю точно то же самое, поэтому не уверен, что компилятор делает какие-либо оптимизации там. Поэтому мой первый вопрос заключается в том, почему компилятор не очищает его и не назначает ему временную переменную?

И мой следующий вопрос: это как-то связано с производительностью? И это более оптимальный код исполнения двух, кроме первого не очень чистого кода. Означает ли это, что мой второй набор строк кода будет внутренне переводиться первым во время компиляции?

И, наконец, последнее, более оптимально ли вызывать переменные в классе, чем метод его получения? Я просто думаю о производительности здесь без чистого кодирования.

+0

Вторая версия будет работать лучше, особенно если 'addressList' является' LinkedList <> 'или некоторым другим' List <> 'where' get' не' O (1) '. (Предположим, вы будете копать глубже первого элемента.) – bradimus

+0

Спасибо @bradimus. Идея заключается в том, что я должен быть усердным в отношении назначения переменных или компилятор Java делает какие-либо оптимизации? Я не уверен. –

+0

Вы можете проверить производительность самостоятельно, сравнив ее. Запустите код несколько thoudsand раз в цикле и измерьте время с помощью '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. 
... 

В результате компилятор не может оптимизировать несколько вызовов методов в один - он должен предполагать, что вызов метода имеет побочные эффекты.

Также стоит отметить, что метод также может быть inlined - здесь тело метода копируется на сайт вызова, чтобы избежать накладных расходов на вызовы методов. Обычно это происходит только тогда, когда JVM считает, что такая оптимизация заслуживает внимания; то есть потому, что его часто называют. Однако это не приводит к тому, что клиентский сайт оптимизируется дальше - он не будет запускать какую-то временную переменную.

Что относительно полей? Они не могут производить побочные эффекты.

Итак, вы теперь думаете об этом:

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

Они не дают побочных эффектов, но компилятор не уронить его во временной переменной либо. Это связано с тем, что побочные эффекты являются двухсторонней улицей - какой-либо другой метод может изменить это поле адресаList; скорее всего, из какой-то другой темы.

+0

Люблю свой ответ Люк, это так много смысла. Я не знаю, почему я не думал об этом с этой точки зрения, и я продолжал думать о геттерах и сеттерах. –

+0

Yup, я больше думал о линиях встроенной замены, когда писал вопрос –

+0

@VishalJumani Нет проблем! У меня было ощущение, что вложение, вероятно, рассматривается (геттеры/сеттеры - это, как правило, первые виды методов, которые можно встроить, из-за того, как часто они привыкают), поэтому было бы целесообразно отказаться от этой дополнительной заметки. –

Смежные вопросы