问题
  简单还原一下问题, 我们有一个类SuperClass
  public class SuperClass {
  private int mSuperX;
  public SuperClass() {
  setX(99);
  }
  public void setX(int x) {
  mSuperX = x;
  }
  }
  现在我们想随时知道mSuperX是什么值, 不用反射, 因为父类从不直接修改mSuperX的值, 总是通过setX来改, 那么简单的方法是继承SuperClass, 重写setX方法, 监听它的改变好.下面是我们的子类SubClass:
  public class SubClass extends SuperClass {
  private int mSubX = 1;
  public SubClass() {}
  @Override
  public void setX(int x) {
  super.setX(x);
  mSubX = x;
  System.out.println("SubX is assigned " + x);
  }
  public void printX() {
  System.out.println("SubX = " + mSubX);
  }
  }
  我使用mSubX来跟踪mSuperX
  因为在ViewGroup中, clipToPadding默认值是true(为了简化问题, 把它当成boolean, 实际并不是), 而ViewGroup初始化有可能不调用setClipToPadding, 此时是默认值, 为了模拟这种情况, 将mSubX初始化为1.
  后在main里调用:
  public class Main {
  public static void main(String[] args) {
  SubClass sc = new SubClass();
  sc.printX();
  }
  }
  很多人, 包括我, 认为终端输出的结果应该是:
  SubX is assigned 99
  SubX = 99
  然而真正运行后输出的是:
  SubX is assigned 99
  SubX = 1
  实际分析
  要想知道发生了什么, 简单的方法是看看到底程序到底是怎么执行的, 比如单步调试, 或者直接一点, 看看Java字节码.
  下面是Main的字节码
  Compiled from "Main.java"
  public class bugme.Main {
  ......
  public static void main(java.lang.String[]);
  Code:
  0: new           #2                  // class bugme/SubClass
  3: dup
  4: invokespecial #3                  // Method bugme/SubClass."<init>":()V
  ......
  }
  这是直接用javap反编译.class文件得到的. 虽说同样是Java写的, 用apktool反编译APK文件(其中的dex文件)得到的smali代码和Java Bytecode明显长得不一样.
  字节码乍一看怪怪的, 只要知道它隐含了一个栈和局部变量表好懂了.
  这段代码首先new一个SubClass实例, 把引用入栈, dup是把栈顶复制一份入栈, invokespecial #3将栈顶元素出栈并调用它的某个方法, 这个方法具体是什么要看常量池里第3个条目是什么, 但是javap生成的字节码直接给我们写在旁边了, 即SubClass.<init>.
  接下来看SubClass.<init>,
  public class bugme.SubClass extends bugme.SuperClass {
  public bugme.SubClass();
  Code:
  0: aload_0
  1: invokespecial #1                  // Method bugme/SuperClass."<init>":()V
  ......
  这里面并没有方法叫<init>, 是因为javap为了方便我们阅读, 直接把它改成类名bugme.SubClass, 顺便一提, bugme是包名. <init>方法并非通常意义上的构造方法, 这是Java帮我们合成的一个方法, 里面的指令会帮我们按顺序进行普通成员变量初始化, 也包括初始化块里的代码, 注意是按顺序执行, 这些都执行完了之后才轮到构造方法里代码生成的指令执行. 这里aload_0将局部变量表中下标为0的元素入栈, 其实是Java中的this, 结合invokespecial #1, 是在调用父类的构造函数, 也是我们常见的super().
  所以我们再看SuperClass.<init>
  public class bugme.SuperClass {
  public bugme.SuperClass();
  Code:
  0: aload_0
  1: invokespecial #1                  // Method java/lang/Object."<init>":()V
  4: aload_0
  5: bipush        99
  7: invokevirtual #2                  // Method setX:(I)V
  10: return
  ......
  }