为什么有些 android 代码有 public 字段?

Why does some android code have public fields?

关于在面向对象编程中使用 public 字段的问题和答案很多,其中大多数建议不要使用 public 字段,原因很多。

但是当我查看 Android 的代码时,我发现一些 类 正在使用 public 字段。例如 Android.view.View 有 public 个字段 mCachingFailedmAttributes.

为什么他们是 public?很难认为这是 Google 和 AOSP 的错误。

public 字段本身并不是错误。正如赏金说明所暗示的那样,它不是 "OOP-fundamental-violation"。毕竟这两个 class 是(对于大多数目的)相同的:

public class DemoA {
  public int field;
}

public class DemoB {
  private int field;

  public int getField() { return field; }
  public void setField(int value) { field = value; }
}

也就是说,如果您打算让调用者直接读写访问一个字段,添加一个getter和setter可能只是是额外的样板。

getters 和 setters 的好处,即使它们除了读取和写入字段之外不做其他工作,也在于它们抽象了数据存储在字段中的事实根本。它可以存储在外部数据源中,或者即时计算,或者任何你想要的,调用者不必担心行为是如何实现的。总的来说,这绝对是一个很好的做法,因为它将调用者的关注点(API)与您的关注点(实施)分开了。

然而,有时它只是矫枉过正,如果这是提供调用者所需行为的最佳方式,那么公开 public 字段是完全合理的。大多数情况下,这样做是为了 value types、class 仅存在 将多个字段组合在一起。当您需要 class 做的所有事情都可以通过简单地制作字段 public.[=13 来完成时,写出 getters 和 setters 的分数几乎没有什么好处=]

作为一个实际问题,Android 还有一个问题。方法调用很昂贵,应用程序可以(轻松)定义的方法数量为 limited to ~65k。在这样做安全的情况下,直接公开字段可以将方法开销减少两倍,并节省宝贵的 CPU 时间。这可能看起来不是很多,但加起来很快。

查看 developer.android.com 中的此部分:

In native languages like C++ it's common practice to use getters (i = getCount()) instead of accessing the field directly (i = mCount). This is an excellent habit for C++ and is often practiced in other object oriented languages like C# and Java, because the compiler can usually inline the access, and if you need to restrict or debug field access you can add the code at any time.

However, this is a bad idea on Android. Virtual method calls are expensive, much more so than instance field lookups. It's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

Without a JIT, direct field access is about 3x faster than invoking a trivial getter. With the JIT (where direct field access is as cheap as accessing a local), direct field access is about 7x faster than invoking a trivial getter.

Note that if you're using ProGuard, you can have the best of both worlds because ProGuard can inline accessors for you

http://developer.android.com/training/articles/perf-tips.html#GettersSetters

这很可能就是您在 AOSP 中看到 public 字段的原因。