Подтвердить что ты не робот

Производительность Android - "Избегайте внутренних Getters/Setters"

Просто прочитайте это на сайте разработчика:

Избегайте внутренних добытчиков/сеттеров

В родных языках, таких как C++, обычной практикой является использование методов получения (например, я = getCount()) вместо прямого доступа к полю (i = mCount). Это отличная привычка для C++, потому что компилятор обычно может встроить доступ, и если вам нужно ограничить или отладить доступ к полю, вы можете добавить код в любое время.

На Android это плохая идея. Вызовы виртуальных методов стоят дорого, намного больше, чем поиск полей экземпляра. Разумно следовать общепринятым методам объектно-ориентированного программирования и иметь в открытом интерфейсе методы получения и установки, но внутри класса вы всегда должны обращаться к полям напрямую.

Без JIT прямой доступ к полю примерно в 3 раза быстрее, чем вызов тривиального геттера. С JIT (где прямой доступ к полю обходится дешевле, чем доступ к локальному), прямой доступ к полю примерно в 7 раз быстрее, чем вызов тривиального геттера. Это верно для Froyo, но улучшится в будущем, когда JIT встроит методы получения.

Обновление в 2019/05: В текущей версии вышеупомянутый материал был удален из документа!

Так что это говорит о том, что вы будете использовать доступ к полям внутри класса:

 public class MyObject {

    public Object innerObject; // This would be private if I was using a getter

    public void doSomeStuff(){
          if(innerObject){        // Within class access like this
                 // ....
          }
    }

    public Object getInnerObject(){  // This would be removed if I was using field access
         return innerObject;
    }
 }

Но как насчет доступа с другого объекта?

 public class SecondObject {

      public void doSecondSomething(){
                MyObject ob = new MyObject();
                Object inner;

                //This is my question basically (from an Android performance perspective)   
                inner = ob.getInnerObject();
                // OR 
                inner = b.innerObject

       }

 }
4b9b3361

Ответ 1

Повышение производительности при использовании внутренних геттеров и сеттеров также распространяется на внешние геттеры и сеттеры.

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

Снижение производительности является результатом ограничений старых JIT-компиляторов Android. Эта ситуация значительно улучшилась с Gingerbread (см. fooobar.com/questions/82499/...... и обратите внимание, кто написал этот ответ!) И продолжает улучшаться. Действительно, в текущей (2019 г.) версии Советов по повышению производительности весь раздел, посвященный внутренним методам получения и установки, был удален.

В общем, плохая идея "настроить" свой код для низшей платформы, особенно если есть разумный шанс, что лучший вариант будет в ближайшем будущем.

Ответ 2

Хотя b.innerObject быстрее, по мере продвижения технологии (лучше cpus, JIT и т.д.) разница между этими двумя параметрами становится меньше.

Единственная точка, где это может иметь значение, - это когда выполняется в интенсивных циклах, которые выполняются все время. Например, в методе onDraw игры, когда вы проходите через сотни объектов.

Ответ 3

// this is faster
inner = b.innerObject

// but this won't hurt performance much because
// it assumed that it will be rare
inner = ob.getInnerObject();

Ответ 4

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

Хорошим примером, где прямой доступ может быть хорошей идеей, является сценарий игры (libgdx)

public abstract class Actor {
    public Group parent;
    public final String name;
    public boolean touchable = true;

    public float x;
    public float y;
    public float width;
    public float height;
    public float originX;
    public float originY;
    public float scaleX = 1;
    public float scaleY = 1;
    public float rotation;
    public final Color color = new Color(1, 1, 1, 1);

Ответ 5

Getters и Setters всегда имеют накладные расходы, поскольку они являются вызовами функций. Когда вы находитесь в одном и том же объекте, вы можете оптимизировать свой код, не используя их, поскольку вы знаете, для чего они используются, и вам не нужно абстрагироваться/инкапсулировать их из своего собственного объекта.

Я думаю, вам также нужно посмотреть на него с другой точки зрения:

  • Не будет ли у вас геттер/сеттер нарушать общие практики? Вы не захотите иметь прямые ссылки, если вы создаете объекты/модули, которые другие будут использовать.

  • Вы действительно не хотите использовать геттеры/сеттеры слишком много раз, как в конце, если только sh! * его оптимизированная из него функциональные вызовы не будут иметь накладных расходов.

Вам действительно нужно оптимизировать базу данных, если я создаю два модуля, в которых некоторые компоненты доступны только друг другу, я могу создать статическое поле, иначе я буду придерживаться getters/seters

Ответ 6

Производительность разумна, нет никакой разницы в доступе к this.field или that.field.

Чувство, что поле экземпляра более доступно объекту, содержащему его, является просто иллюстрацией синтаксиса.

OO, серьезно, насколько сложным может стать приложение для Android? Многие мантры OO - это создание монстров. Какое большое дело, если ваше маленькое приложение использует объекты типа structs?

И даже в огромном приложении, если он находится в доме, и все исходные коды, получающие доступ к полю, доступны для рефакторинга, нет никаких проблем при экспонировании полей.

Ответ 7

Для записи другая проблема с установщиком и getter (на Java) - это то, что они ужасно уродливы в использовании.

Скажем, следующее упражнение, нам нужно изменить поле в поле зрения поля объекта

В java есть:

   object.getField().getSubField().setField3("hello"); // ugly

В то время как в С# тот же код (даже с инкапсуляцией)

   object.Field.SubField.Field3="hello";  // fine

Таким образом, использование открытого поля в Java (или Android) намного чище:

  object.field.subfield.field3="hello"; // fine too