多态虚方法

方法的分类:

之前是按照是否有static修饰,分为静态方法和非静态方法。
现在按照新的分类标准,是否可以被重写:

非虚方法:除了虚方法以外的方法都叫做非虚方法。
              静态方法,私有方法,构造器对应的实例初始化方法,final的方法等等。
虚方法:可以被重写的方法
JVM是模拟真实的计算机而设计的一个运行环境,里面设计了很多指令,它不完全等价于CPU指令。
JVM的指令。
这些指令有很多,其中关于方法调用有这样的一些指令:
invokestatic:调用静态方法的指令
invokespecial:调用的是私有方法的指令
invokevirtual:调用的虚方法的指令,这里final的方法虽然也是用这个指令执行的,但是它归到非虚方法里面。因为final修饰的方法是不能被重写。
多态引用的形式下:
非虚方法的访问原则:只看编译时类型
虚方法的访问原则:编译时看父类,运行时看子类重写与否
/*
面试题:虚方法调用的过程和运行结果(难)
分析步骤:
(1)method方法发生调用时,判断method方法是否是虚方法?
是虚方法。就按照下面的四步走。
如果不是虚方法,只看编译时类型。

(2)看调用method方法的变量的编译时类型是什么?
my的编译时类型是MyClass类型

(3)在编译时类型中寻找调用哪个method方法?
此时的依据是实参与形参的匹配问题。实参和形参的匹配原则:
A:找最匹配的
    匹配是按照实参的编译时类型来匹配。
B:找能够兼容

(4)看调用method方法的变量的运行时类型是什么?
这里,my的编译时类型和运行时类型一致,
my的运行时类型是MyClass类型,就执行MyClass类型中找到的最匹配的method方法。

如果调用method方法的变量的运行时类型是子类,就看子类是否重写了该方法,
如果没有重写,仍然执行刚找到最匹配的方法,
如果有重写,就执行重写的代码。
 */
public class TestExam {
    public static void main(String[] args) {
        Father f = new Father();
        Father s = new Son();
        Father d = new Daughter();

        MyClass my = new MyClass();
        my.method(f);//father
            /*
            (1)在MyClass类型中找最匹配的method方法,看实参与形参的匹配程度。
              实参的编译类型 与 哪个方法的形参类型最匹配
              实参是f,它的编译时类型是Father,与public void method(Father f) 最匹配
             (2)因为my变量的运行时类型仍然是MyClass,所有还是执行刚刚找到的method
             */
        my.method(s);//father
            /*
            (1)在MyClass类型中找最匹配的method方法,看实参与形参的匹配程度。
              实参的编译类型 与 哪个方法的形参类型最匹配
              实参是s,它的编译时类型是Father,与public void method(Father f) 最匹配
             (2)因为my变量的运行时类型仍然是MyClass,所有还是执行刚刚找到的method
             */
        my.method(d);//father
            /*
            (1)在MyClass类型中找最匹配的method方法,看实参与形参的匹配程度。
              实参的编译类型 与 哪个方法的形参类型最匹配
              实参是d,它的编译时类型是Father,与public void method(Father f) 最匹配
             (2)因为my变量的运行时类型仍然是MyClass,所有还是执行刚刚找到的method
             */
    }
}
class MyClass{
    //问题1:这三个方法是什么关系?
    //重载
    public void method(Father f) {
        System.out.println("father");
    }
    public void method(Son s) {
        System.out.println("son");
    }
    public void method(Daughter f) {
        System.out.println("daughter");
    }
}
class Father{

}
class Son extends Father{

}
class Daughter extends Father{

}
public class TestExam2 {
    public static void main(String[] args) {
        Father f = new Father();
        Son s = new Son();
        Daughter d = new Daughter();

        MyClass my = new MyClass();
        my.method(f);//father
            /*
            (3)在MyClass类中,找最匹配的method方法
                实参的编译时类型与形参类型最匹配
                实参f的编译时类型是Father类,与 public void method(Father f)最匹配
            (4)my的运行时类型还是MyClass,所以执行刚找到的method方法
             */
        my.method(s);//son
             /*
            (3)在MyClass类中,找最匹配的method方法
                实参的编译时类型与形参类型最匹配
                实参s的编译时类型是Son类,与 public void method(Son s)最匹配
            (4)my的运行时类型还是MyClass,所以执行刚找到的method方法
             */
        my.method(d);//father
            /*
            (3)在MyClass类中,找最匹配的method方法
                实参的编译时类型与形参类型最匹配
                实参d的编译时类型是Daughter类,与 public void method(Father f) 兼容
            (4)my的运行时类型还是MyClass,所以执行刚找到的method方法
             */
    }
}
class MyClass{
    public void method(Father f) {
        System.out.println("father");
    }
    public void method(Son s) {
        System.out.println("son");
    }
}
class Father{

}
class Son extends Father{

}
class Daughter extends Father{

}
public class TestExam3 {
    public static void main(String[] args) {
        Father f = new Father();
        Son s = new Son();
        Daughter d = new Daughter();

        MyClass my = new MySub();
        my.method(f);//father
            /*
            (3)在MyClass中找最匹配或兼容的方法
            实参的编译类型与形参的类型匹配
            实参f的编译时类型是Father,与public void method(Father f)最匹配
            (4)my的运行时类型是MySub,就要看MySub中是否重写了method(Father f)方法
            这里没有重写。还是执行刚刚在MyClass中找到的方法。
             */
        my.method(s);//son
            /*
            (3)在MyClass中找最匹配或兼容的方法
            实参的编译类型与形参的类型匹配
            实参s的编译时类型是Son,与public void method(Son f) 最匹配
            (4)my的运行时类型是MySub,就要看MySub中是否重写了 method(Son s)方法
            这里没有重写。还是执行刚刚在MyClass中找到的方法。
             */
        my.method(d);//father
            /*
            (3)在MyClass中找最匹配或兼容的方法
            实参的编译类型与形参的类型匹配
            实参d的编译时类型是Daughter,与public void method(Father f) 兼容
            (4)my的运行时类型是MySub,就要看MySub中是否重写了 method(Father f)方法
            这里没有重写。还是执行刚刚在MyClass中找到的方法。
             */
    }
}
class MyClass{
    public void method(Father f) {
        System.out.println("father");
    }
    public void method(Son s) {
        System.out.println("son");
    }
}
class MySub extends MyClass{
    public void method(Daughter d) {
        System.out.println("daughter");
    }
}
class Father{

}
class Son extends Father{

}
class Daughter extends Father{

}
public class TestExam4 {
    public static void main(String[] args) {
        MyClass my = new MySub();
        Father f = new Father();
        Son s = new Son();
        Daughter d = new Daughter();
        my.method(f);//daughter
        /*
        (3)在my的编译时类型MyClass中找匹配的方法
        实参f的编译时类型与形参Father类型最匹配,找到public void method(Father f)
        (4)看my的运行时类型,MySub,
        MySub中是否重写了public void method(Father f)
        是重写了,就执行重写的public void method(Father f) 方法
         */
        my.method(s);//son
         /*
        (3)在my的编译时类型MyClass中找匹配的方法
        实参s的编译时类型与形参Son类型最匹配,找到public void method(Son s)
        (4)看my的运行时类型,MySub,
        MySub中是否重写了public void method(Son s)
        没有重写,还是执行MyClass中找到public void method(Son s)
         */
        my.method(d);//daughter
         /*
        (3)在my的编译时类型MyClass中找匹配的方法
        实参d的编译时类型Daughter与形参Father类型兼容,找到 public void method(Father f)
        (4)看my的运行时类型,MySub,
        MySub中是否重写了 public void method(Father f)
        是重写,执行重写的 public void method(Father f)
         */
    }
}
class MyClass{
    public void method(Father f) {
        System.out.println("father");
    }
    public void method(Son s) {
        System.out.println("son");
    }
}
class MySub extends MyClass{
    public void method(Father f) {
        System.out.println("daughter");
    }
}
class Father{

}
class Son extends Father{

}
class Daughter extends Father{

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值