是方法覆盖还是重载?

时间:2017-06-10 11:40:59

标签: java overloading override method-overriding

git reset --hard HEAD

输出

public class Tester {
   public static void main(String[] args) {
      A a2 = new B();
      a2.dosomething1(new B());
      a2.dosomething2(new B());
   }
}

class A {
   public void dosomething1(A a){
      System.out.println("Inside a  dosomething1");
   }

   public void dosomething2(A a){
      System.out.println("Inside a  dosomething2");
   }
}

class B extends A {
   public void dosomething1(A a){
      System.out.println("Inside b dosomething1");
   }

   public void dosomething2(B b){
      System.out.println("Inside b  dosomething2");
   }
}

输出中的第一行显然是由于方法覆盖。 但是第二线背后的原因是什么?为什么java没有调用B中定义的方法,因为在运行时它知道a2是B的对象。

2 个答案:

答案 0 :(得分:6)

您需要回答的问题是:B.dosomething2(B b)可以完全取代A.dosomething2(A a)吗?或者更具体地说:A.dosomething2(A a)接受的每个参数值是否也可以传递给B.dosomething2(B b)

答案很简单:不。

B obj_B= new B();
A obj_A= new A();
obj_B.doSomething2(obj_A);

上面的示例应明确原因:obj_A不是B的实例,因此无法作为参数传递给B.dosomething2(B b)。这意味着这两种方法虽然共享相同的名称但不共享相同的签名,这反过来意味着我们重载该方法而不是覆盖它。

事实上,碰巧用适合两者的东西调用它是无关紧要的,因为选择哪个重载方法在Java编译时调用,基于变量{ {1}}的类型(a2)而不是它指向的对象的运行时类(A)。

这种错误很容易发生,特别是如果你改变你的方法并重命名它们。为了避免在意图重写时意外重载,请确保在打算覆盖某些内容时始终使用B注释,这样编译器会抱怨。

@Override

这个注释在技术上是可选的,但它非常有用,在实践中人们将其视为强制性的。

答案 1 :(得分:2)

方法重写

  

为什么java没有调用B中定义的方法,因为在运行时它知道a2   是B的对象。

因为class B extends A { @Override //this will compile fine public void dosomething1(A a){ System.out.println("Inside b dosomething1"); } @Override //this will fail compilation public void dosomething2(B b){ System.out.println("Inside b dosomething2"); } } 中的dosomething2A中的dosomething2具有不同的签名。
您没有在B覆盖dosomething2。关于动态调度,B中的dosomething2是一种新方法。