Java:重载方法

时间:2012-03-13 23:24:22

标签: java oop inheritance overloading

我想知道为什么要打电话

z.f(-6);
类M中的

指的是B类中的以下函数:

public void f(double y) {
    this.x = (int) y + B.y;
}

而不是在A类中使用函数f,因为b。涵盖了A。或者更确切地说是使用

public void f (int y) {
    this.x = y*2;
    B.y = this.x;
}
在B类中

,其中至少参数类型匹配。

以下完整代码:

public class A {
    public int x = 1;
    public A(int x) {
        this.x += x;
    }
     public A (double x) {
        x += x;
    }
    public void f(double x) {
        this.x = this.x + (int) (x + B.y);
    }
}

public class B extends A {
    public static int y = 3;
    public int x = 0;
    public B (double x) {
        super((int) x);
    }
    public void f(int y) {
        this.x = y*2;
        B.y = this.x;
    }
    public void f(double y) {
        this.x = (int) y + B.y;
    }
  }

public class M {
      public static void main (String[] args){
        A a = new A(B.y);
        a.f(1);
        B b = new B(3.0);
        A z = b;
        z.f(-5.0);
        z.f(-6);
        System.out.println(b.x + "   " + z.x);
       }
  }

4 个答案:

答案 0 :(得分:3)

z的静态类型为A,因此z.f(-6)只能绑定到A中的方法,在本例中为A.f(int)

语言是这样设计的,以便

A z = new B(3.0);
z.f(-6);

将始终与

相同
A z = complicatedWayToComputeTrue() ? new B(3.0) : new A(3.0);
z.f(-6);

如果编译器要绑定到不同的方法签名,因为它可以证明A z总是持有B,那么这会为语言引入各种非局部效果,使其变得非常困难调试或维护java程序。

想象一下有人试图维持

final A z = complicatedWayToComputeTrue() ? new B(3.0) : new A(3.0);
// 1000 lines elided
z.f(-6);

将其更改为

A z = new B(3.0);
// 1000 lines elided
z.f(-6);

如果编译器现在可以证明A始终是B并将Z.f绑定到B中的方法,那么维护者将会感到困惑。

答案 1 :(得分:3)

z.f(-6);

z的静态类型为A,其中只有一个名为f的方法。该方法采用double参数,可以提升文字值-6。因此,在编译时,调用绑定到A.f(double)

在运行时z发现类型为B,它会使用自己的A.f(double)覆盖B.f(double),这样就可以调用此方法。

答案 2 :(得分:1)

Java是单一调度,而您尝试执行的是double dispatch(调用的方法取决于动态运行时类和参数)。

在Java中调用的方法的签名是在编译时确定的;这意味着对象的声明类确定绑定哪个方法。覆盖子类中的方法会影响绑定的实现,但是重载方法不会(因为重载的方法具有不同的签名)。

在类B中,你使用一个带有int的版本重载f(),当使用一个声明为类A的对象时,这个方法似乎不存在(你不能调用它,也不会调用它) )。

总结:

  • 编译器在编译时绑定到方法签名。
  • 此绑定签名取决于对象和参数的声明(编译时)类型。
  • 如果在子类中重写了一个方法,那么在调用子类时(无论声明的类型如何),都将选择重写的方法。
  • 重载不会覆盖,覆盖你需要相同的方法签名(好吧,除了协方差)。

答案 3 :(得分:0)

我可能错了,但如果您将z类型的对象A链接到类型为B的对象,它仍会绑定为B类型,这就是它在类B而不是在类A中执行方法的原因。请注意,由于您未使用A,因此不会创建new类型的对象。

正如Mike Samuel所说,默认-6应被视为int,但这不符合您的解释。我会试着找到一个合适的答案。