请在开发网站上阅读:
Avoid Internal Getters/Setters
在像C ++这样的本地语言中,通常的做法是使用getter(例如i = getCount())而不是直接访问字段(i = mCount)。这是C ++的一个很好的习惯,因为编译器通常可以内联访问,如果你需要限制或调试字段访问,你可以随时添加代码。
在Android上,这是一个坏主意。虚拟方法调用比实例字段查找要昂贵得多。遵循常见的面向对象编程实践并在公共接口中使用getter和setter是合理的,但在类中,您应该始终直接访问字段。
没有JIT,直接字段访问速度比调用一个简单的getter快约3倍。使用JIT(直接字段访问与访问本地一样便宜),直接字段访问比调用一个简单的getter快约7倍。在Froyo中也是如此,但是当JIT内联getter方法时,将会有所改进。
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
}
}
答案 0 :(得分:31)
使用内部getter和setter的性能影响也适用于外部getter和setter。
然而,在外部情况下,吸气剂和制定者在其他方面具有显着的益处;例如保持封装,减少有害耦合,使代码更易于维护,等等。因此,尽管可能会产生性能损失,但通常将其视为使用getter和setter的最佳实践。
性能损失是旧版Android JIT编译器限制的结果。使用Gingerbread可以显着改善这种情况(参见 - https://stackoverflow.com/a/4930538/139985 ...并注意谁写了这个答案!)并继续改进。实际上,在Performance Tips的当前(2019)版本中,关于内部吸气剂和定位器的整个部分已被删除。
一般来说,为一个劣质平台“调整”你的代码是一个坏主意,特别是如果有一个合理的机会,一个更好的一个即将到来。
答案 1 :(得分:4)
尽管b.innerObject
更快,但随着技术的进步(更好的cpus,JIT等),两个选项之间的差异会变小。
唯一可能重要的一点是在一直执行的密集循环中完成。例如,在游戏的onDraw
方法中,当你循环遍历数百个对象时。
答案 2 :(得分:3)
// this is faster
inner = b.innerObject
// but this won't hurt performance much because
// it's assumed that it will be rare
inner = ob.getInnerObject();
答案 3 :(得分:3)
请注意,只有当相关成员每秒访问数千次时,这些性能注意事项才有意义。
直接访问可能是一个好主意的一个很好的例子是游戏的场景图(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);
答案 4 :(得分:2)
Getters和Setter总是有一个开销,因为它们是函数调用。当您在同一个对象中时,可以通过不使用它们来优化代码,因为您知道它们的用途,并且您不需要从它自己的对象中抽象/封装它们。
我认为您还需要从不同的角度来看待它:
没有getter / setter会破坏常见的oops做法吗?如果您正在制作其他人将使用的对象/模块,您将不希望有直接引用。
你真的不想在最后使用getter / setter太多次,除非sh!*优化了它的函数调用会产生开销。
你真的需要在percase的基础上进行优化,如果我构建两个模块,其中一些组件只能彼此访问,我可能会创建一个静态字段,否则我会坚持getter / setters
答案 5 :(得分:2)
性能方面,访问this.field
或that.field
没有区别。
托管它的对象更容易访问实例字段的感觉只是一种语法错觉。
OO明智地,认真地说,Android应用程序有多复杂?许多OO咒语来自构建怪物应用程序。如果你的小应用程序使用像结构这样的对象,那有什么大不了的呢?
即使在一个巨大的应用程序中,只要它在内部,并且所有访问字段的源代码都可用于重构,所以暴露字段完全没有问题。
答案 6 :(得分:0)
对于记录,setter和getter(在Java中)的另一个问题是它们使用起来很难看。
让我们说下一个练习,我们需要修改一个字段内部的字段
在java中是:
object.getField().getSubField().setField3("hello"); // ugly
在C#中,相同的代码(即使使用封装)
object.Field.SubField.Field3="hello"; // fine
因此,在Java(或android)中使用公共字段要清晰得多:
object.field.subfield.field3="hello"; // fine too