再看看反编译的结果:
  javap -c Test
  警告: 二进制文件Test包含CoreJava.day_2.Test
  Compiled from "Test.java"
  public class CoreJava.day_2.Test {
  public CoreJava.day_2.Test();
  Code:
  0: aload_0
  1: invokespecial #1                  // Method java/lang/Object."<init>":()V
  4: return
  public static void main(java.lang.String[]);
  Code:
  0: new           #2                  // class java/lang/String
  3: dup
  4: invokespecial #3                  // Method java/lang/String."<init>":()V
  7: astore_1
  8: new           #4                  // class CoreJava/day_2/Test$SecLee
  11: dup
  12: invokespecial #5                  // Method CoreJava/day_2/Test$SecLee."<init>":()V
  15: astore_2
  16: aload_2
  17: aload_1
  18: invokevirtual #6                  // Method CoreJava/day_2/Test$Lee.say:(Ljava/lang/String;)V
  21: return
  }
  正如上面的结果,18: invokevirtual #6 // Method CoreJava/day_2/Test Lee.say:(Ljava/lang/String;)V这里是TestLee.say而非Test$SecLee.say,因为编译期无法确定调用子类还是父类的实现,所以只能丢给运行时的动态绑定来处理。
  既然重写测试了,那我们再试试重载:
  下面的例子更复杂!Lee类中存在say方法的两种重载,更复杂的是SecLee集成Lee并且重写了这两个方法。其实这种情况是上面两种情况的复合情况。
  下面的代码首先会发生静态绑定,确定调用参数为String对象的say方法,然后在运行时进行动态绑定确定执行子类还是父类的say实现。
  public class Test {
  public static void main(String[] args) {
  String str = new String();
  Lee lee = new SecLee();
  lee.say(str);
  }
  static class Lee {
  public void say(Object obj) {
  System.out.println("这是Object");
  }
  public void say(String str) {
  System.out.println("这是String");
  }
  }
  static class SecLee extends Lee {
  @Override
  public void say(Object obj) {
  System.out.println("这是第二李的Object");
  }
  @Override
  public void say(String str) {
  System.out.println("这是第二李的String");
  }
  }
  }
  结果:
  $ java Test
  这是第二李的String
  结果在意料之中,不多说了。
  那么问题来了,非动态绑定不可么?
  其实某些方法的绑定也可以由静态绑定实现,比如说:
  public static void main(String[] args) {
  String str = new String();
  final Lee lee = new SecLee();
  lee.say(str);
  }
  可以看出,这里lee持有SecLee的对象并且lee变量为final,立即执行了say方法,编译器理论上通过足够的分析代码,是可以知道应该调用SecLee的say方法。
  结论:
  由于动态绑定需要在运行时确定执行哪个版本的方法实现或者变量,比起静态绑定起来要耗时,所以正如书上所说的,有些程序员认为,除非有足够的理由使用多态性,应该把所有的方法都声明为final,private或者static进行修饰。我觉得这个有点偏激了,具体使用仁者见仁,智者见智吧。