案例分析

  • 源代码一

    class Super {
      private void test () {
        System.out.println( "super" );
      }
    
      public void invoke () {
        test();
      }
    }
    
    class Suber extends Super {
      public void test () {
        System.out.println( "suber" );
      }
    }
    
    // 调用
    public class TestClass7 {
      public static void main (String[] args) {
          new Suber().invoke();
      }
    }
    
  • 结果

    super
    
  • 源代码二

    class Super {
      public void test () {
        System.out.println( "super" );
      }
    
      public void invoke () {
        test();
      }
    }
    
    class Suber extends Super {
      public void test () {
        System.out.println( "suber" );
      }
    }
    
    // 调用
    public class TestClass7 {
      public static void main (String[] args) {
          new Suber().invoke();
      }
    }
    
  • 结果

    suber
    
  • 分析

    对于源代码一和源代码二来说, 仅仅只是Super类的test方法的权限不同, 一个为private, 一个为public,
    那么对于源代码一来说, invoke方法是由Suber类实例来调用的, 在编译阶段, 由于invoke方法在Super类中,
    那么其对test方法进行查看, 发现在Super类中存在一个private的test方法, 由此认为test方法是非虚方法,
    对于非虚方法来说, 字节码中对该方法的调用应该用invokespecial, 并且是能够在加载阶段确定的, 而对于
    源代码二中, 对test方法进行查看时, 没有发现非虚方法test, 所以该方法的调用由运行期间来决定, 在运行
    时调用test方法, 由于子类Suber重写了test方法, 根据动态分派, 首先应该先查询调用者的实际类型(Suber)
    中是否存在test方法, 存在即调用, 所以在invoke方法中调用的是重写的test的方法
    

results matching ""

    No results matching ""