考虑一下此代码(为简洁起见,完整的类,运行良好的所有类都在一个类中)。

我的问题在代码清单后:

import java.util.LinkedList;
import java.util.List;

class Gadget {
    public void switchon() {
        System.out.println("Gadget is Switching on!");
    }
}

interface switchonable {
    void switchon();
}

class Smartphone extends Gadget implements switchonable {
    @Override
    public void switchon() {
        System.out.println("Smartphone is switching on!");
    }
}

class DemoPersonnel {
    public void demo(Gadget g) {
        System.out.println("Demoing a gadget");
    }

    public void demo(Smartphone s) {
        System.out.println("Demoing a smartphone");
    }
}

public class DT {

    /**
     * @param args
     */
    public static void main(String[] args) {
        List<Gadget> l = new LinkedList<Gadget>();
        l.add(new Gadget());
        l.add(new Smartphone());
        for (Gadget gadget : l) {
            gadget.switchon();
        }

        DemoPersonnel p = new DemoPersonnel();
        for (Gadget gadget : l) {
            p.demo(gadget);
        }
    }
}

问题:
  • 从编译器的角度来看,智能手机中switchon方法的起源是什么?它是从基类小工具继承的吗?还是由可切换接口强制执行的切换方法的实现?注释在这里有什么区别吗?
  • 在主方法中,第一个循环:在这里,我们看到了运行时多态的一种情况-即,当第一个for循环正在运行,并且调用了gadget.switchon()时,它首先打印“Gadget is turn on on”,然后它会显示“智能手机正在打开”。但是在第二个循环中,不会发生运行时解析,并且两次调用demo的输出都是“Demoing a gadget”,而我原本希望它在第一次迭代时打印“Demoing a gadget”,然后“Demoing a Smartphone”第二次。

  • 我理解错了什么?为什么运行时在第一个for循环中解析子类,但在第二个for循环中不解析子类?

    最后,将链接到有关Java中运行时/编译时多态性的清晰教程的链接。 (请不要发布Java教程的跟踪链接,当在适当的深度讨论更细微的差别时,我发现材料没有特别令人印象深刻)。

    最佳答案

    这是短期内的工作方式:
    编译时间

  • 编译器为请求的方法
  • 定义了必需的签名
  • 一旦定义了签名,编译器就会开始在类型类
  • 中寻找它。
  • 如果发现任何兼容的候选方法并带有所需的签名,则返回

  • 运行时
  • 在执行过程中,JVM开始寻找签名方法为且在编译时定义为的候选方法。
  • 搜索可执行方法实际上是从实际的Object实现类(可以是Type-Class的子类)开始,然后向上浏览整个层次结构。

  • 您的列表是用小工具类型定义的。
    for (Gadget gadget : l) {
            gadget.switchon();
        }
    

    当您要求gadget.switchon();时,编译器将在Gadget类中寻找switchon()方法,并且在那里,候选签名仅被确认为switchon()

    在执行期间,JVM将从Smartphone类中寻找switchon()方法,这就是为什么它显示正确的消息。

    这是第二个for循环中发生的情况
    DemoPersonnel p = new DemoPersonnel();
        for (Gadget gadget : l) {
            p.demo(gadget);
        }
    

    在这种情况下,签名是针对两个对象demo(Gadget g)的,这就是为什么对于两个迭代都执行demo(Gadget g)方法的原因。

    希望能帮助到你!

    07-26 03:13