Производительность 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
}
}
Ответы
Ответ 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