Java 安卓系统性能-';避免内部getter/setter';

Java 安卓系统性能-';避免内部getter/setter';,java,android,performance,optimization,Java,Android,Performance,Optimization,只需在开发人员网站上阅读以下内容: 在C++等本地语言中,使用GETTER(例如,I= GETCONTUTE())代替直接访问字段(I= MCOUNT)是常见的做法。对于C++来说,这是一个很好的习惯,因为编译器通常可以内联访问,如果需要限制或调试字段访问,则可以随时添加代码。 在Android上,这是个坏主意。虚拟方法调用的开销比实例字段查找要大得多。遵循常见的面向对象编程实践并在公共接口中使用getter和setter是合理的,但是在类中,您应该始终直接访问字段 如果没有JIT,直接字段访

只需在开发人员网站上阅读以下内容:

在C++等本地语言中,使用GETTER(例如,I= GETCONTUTE())代替直接访问字段(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

       }

 }

尽管
b.innerObject
速度更快,但随着技术的进步(更好的CPU、JIT等),这两个选项之间的差异变得更小


唯一重要的一点是,在始终执行的密集循环中执行时。例如,在游戏的
onDraw
方法中,当你在数百个对象中循环时

请记住,只有当相关成员每秒被访问数千次时,这些性能考虑才是相关的

直接访问可能是一个好主意的一个很好的例子是游戏的场景图()


使用内部getter和setter对性能的影响也适用于外部getter和setter

然而,在外部情况下,接受者和接受者在其他领域有显著的优势;e、 保留封装,减少有害耦合,使代码更易于维护,等等。因此,使用getter和setter通常被认为是最佳实践,尽管这可能会导致性能下降

性能下降是旧版Android JIT编译器局限性的结果。姜饼显著改善了这种情况(见-…并注意是谁写的答案!),并且继续改善。事实上,在当前(2019)版本的中,关于内部getter和setter的整个建议部分已经删除


一般来说,为劣质平台“调优”代码是一个坏主意,特别是如果有一个合理的机会,一个更好的平台即将出现

由于getter和setter是函数调用,因此它们总是有开销。当您在同一个对象中时,您可以通过不使用它们来优化代码,因为您知道它们的用途,并且不需要从它自己的对象中抽象/封装它们

我认为你也需要从不同的角度来看待它:

  • 没有getter/setter会打破常见的oops实践吗?如果您正在创建其他人将使用的对象/模块,则不希望直接引用

  • 你真的不想在最后多次使用getter/setter,除非sh!*其优化的out-it函数调用将产生开销


  • 您确实需要在percase基础上进行优化,如果我正在构建两个模块,其中一些组件只能由彼此访问,我可能会创建一个静态字段,否则我将坚持使用getter/setters

    性能方面,访问
    this.field
    this.field
    没有区别

    实例字段更容易被承载它的对象访问的感觉只是一种语法错觉

    哦,说真的,Android应用程序会变得多复杂?许多OO咒语来自于构建怪物应用程序。如果你的小应用程序使用像structs这样的对象,有什么大不了的


    即使在一个巨大的应用程序中,只要它在内部,并且访问某个字段的所有源代码都可用于重构,那么公开字段就没有任何问题

    请注意,setter和getter(在Java中)的另一个问题是它们使用起来很麻烦

    假设在下一个练习中,我们需要在对象的字段中修改字段

    在java中是:

       object.getField().getSubField().setField3("hello"); // ugly
    
    而在C#中,相同的代码是(即使使用封装)

    因此,在Java(或android)中使用公共字段要干净得多:

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

    要指出这一点,请记住Dalvik不是JVM,这种做法不应该被视为普通Java开发中的一般做法?遵循常见的面向对象编程实践并在公共接口中使用getter和setter是合理的。另外:不要过度设计。只要使用getter,除非你做了大量的调用。或者速度有问题。等等,android JIT不内联琐碎的函数调用?我的意思是,这是任何JIT的基本优化之一-确保它必须确保类没有被覆盖等等,但这是99/100 easy中的一个。很难相信。@Voo-商业原因可能使得现在就有必要交付二流产品,而不是等待6个月直到它成为一流产品。Java和Javascript(以及Windows Vista和…)也发生了同样的事情。如果你忽略历史,这只是“很难相信”而已。“getter和setter总是有开销,因为它们是函数调用”在任何现代的JIT-in热点上都是不正确的,除非在一些罕见的情况下是内联的(即setter实际上在子类中被覆盖,jit不能保证对象的身份之一——或者说,几乎从来没有)啊,但这是TrainCrank反模式,只与最近的邻居交谈并获取代码<
       object.getField().getSubField().setField3("hello"); // ugly
    
       object.Field.SubField.Field3="hello";  // fine
    
      object.field.subfield.field3="hello"; // fine too