Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多态性不';不能在Java中使用方法参数_Java_Oop_Polymorphism - Fatal编程技术网

多态性不';不能在Java中使用方法参数

多态性不';不能在Java中使用方法参数,java,oop,polymorphism,Java,Oop,Polymorphism,我编写了以下代码: class Plane {} class Airbus extends Plane {} public class Main { void fly(Plane p) { System.out.println("I'm in a plane"); } void fly(Airbus a) { System.out.println("I'm in the best Airbus!"); } publi

我编写了以下代码:

class Plane {}
class Airbus extends Plane {}

public class Main {

    void fly(Plane p) {
        System.out.println("I'm in a plane");
    }

    void fly(Airbus a) {
        System.out.println("I'm in the best Airbus!");
    }

    public static void main(String[] args) {

        Main m = new Main();

        Plane plane = new Plane();
        m.fly(plane);

        Airbus airbus = new Airbus();
        m.fly(airbus);

        Plane planeAirbus = new Airbus();
        m.fly(planeAirbus);

    }
}
结果是:

I'm in a plane
I'm in the best Airbus!
I'm in a plane
不出所料,前两次调用给出了
我在飞机上
我在最好的空中客车上分别为

Plane planeAirbus = new Airbus();
该方法将此对象视为平面,即使真实对象是一个平面。即使我将
抽象
添加到
类平面
,也没有任何变化,最后一次调用的结果仍然是
我在一个平面


所以问题是为什么多态性在方法参数和调用中不起作用?这有什么目的吗?它是如何工作的

这里的问题是Java不支持方法参数的动态绑定。您看到的是静态绑定,即要调用的方法的重载是在编译时选择的


另请参见:以下输出的原因:

I'm in a plane
I'm in the best Airbus!
I'm in a plane

因为它正在执行重载,而重载是静态多态或编译时多态。在重载中,类可以有多个同名但参数类型不同的方法。在您的示例中,
Plane
Plane planeAirbus=new Airbus()的类型

方法重载类型多态性在Java中是在编译时确定的

这意味着Java必须从它们表示的引用类型推断出方法参数的类型,因为它不知道它们在编译时持有的对象的类型。 我们可以说,在这种情况下,Plane类型的引用保存Airbus类型实例是非常清楚的。然而,这并不是那么简单,因为空客实例本身可能是一个方法参数,它可以保存任何子类实例或空客实例本身

唯一安全的方法是不解析父链,并将引用作为其面值的实际引用变量类型。另一种方法是实现与重写相同的方法重载,并使用对象的运行时绑定进行解析。我不知道为什么不这样做,因为这样会使方法重载和重写更加统一

以下是来自

调用方法时(§15.12),在编译时使用实际参数(以及任何显式类型参数)的数量和参数的编译时类型来确定将调用的方法的签名(§15.12.2)。如果要调用的方法是实例方法,则将在运行时使用动态方法查找(§15.12.4)确定要调用的实际方法。
Java重载是编译时多态性。因此,当您将
planeAirbus
声明为
Plane
时,它将调用
fly(Plane)

事实上,class
Main
不应该知道
飞机和
空客可以飞行。
更好的it设计:

public interface Flyable{
  void fly();
}

public Plane implements Flyable{
  void fly(){
     //do something
  }
}

 public Airbus implements Flyable{
    void fly(){
       //do something
    }
 }
然后在
Main
类中

public static void main(String[] args) {
  Flyable plane = new Plane();
  plane.fly();

  Flyable airbus = new Airbus();
  airbus.fly();
}

动态绑定的另一个名称是双重分派还是有不同的概念?我认为双重分派是不同的,但是双重分派通常也实现动态绑定,所以它们经常一起出现。双重分派可以在Java中通过使用访问者模式来实现,因为Java是一种静态类型的语言。