Java中的函数覆盖 – 重载
覆盖和重载有什么区别?
-
重载:根据指定参数的数量和类型在编译时选择方法签名
-
覆盖:根据目标对象的实际类型在执行时选择方法实现 (而不是表达式的编译时类型)
例如:
class Base { void foo(int x) { System.out.println("Base.foo(int)"); } void foo(double d) { System.out.println("Base.foo(double)"); } } class Child extends Base { @Override void foo (int x) { System.out.println("Child.foo(int)"); } } ... Base b = new Child(); b.foo(10); // Prints Child.foo(int) b.foo(5.0); // Prints Base.foo(double)
这两个调用都是重载的例子。 有两种方法称为foo
,编译器确定要调用的签名。
第一个调用是覆盖的示例。 编译器选择签名“foo(int)”,但是在执行时,目标对象的类型确定要使用的实现应该是Child
。
-
重载方法是一种编译技巧,允许您使用相同的名称根据参数执行不同的操作。
-
覆盖方法意味着它的整个function正在被替换。 覆盖是在子类中对父类中定义的方法执行的操作。
src: http : //www.jchq.net/tutorial/06_02Tut.htm
重载:
public Bar foo(int some); public Bar foo(int some, boolean x); // Same method name, different signature.
覆盖:
public Bar foo(int some); // Defined in some class A public Bar foo(int some); // Same method name and signature. Defined in subclass of A.
如果没有定义第二个方法,它将inheritance第一个方法。 现在它将被A的子类中的第二个方法替换。
重载 – 类似签名 – 相同名称,不同参数
void foo() { /** overload */ } void foo( int a ) { /** overload */ } int foo() { /** this is NOT overloading, signature is for compiler SAME like void foo() */ }
覆盖 – 您可以在inheritance方法体时重新定义方法体。
class A { void foo() { /** definition A */ } } class B extends A { void foo() { /** definition B, this definition will be used when you have instance of B */ } }
有趣的是要提到:
public static doSomething(Collection> c) { // do something } public static doSomething(ArrayList> l) { // do something } public static void main(String[] args) { Collection c = new ArrayList (); doSomething(c); // which method get's called? }
可以假设使用ArrayList参数的方法将被调用,但事实并非如此。 调用第一个方法,因为在编译时选择了正确的方法。
覆盖
是否在子类中替换 (重写)由超类的子类inheritance的方法。
class A { void foo() { /** definition A of foo */ } } class B extends A { void foo() { /** definition B of foo */ } }
现在如果你使用以下方法调用foo
:
A a = new B(); a.foo();
将运行foo
的B
定义。 这不是那么直观,因为如果A
类没有名为foo
的方法,您将收到编译错误。 因此,对象的类型 A
必须具有方法foo
,然后可以调用它,并且将执行实例的方法foo
,即B
类的方法,因此是“执行时间”。
超载
创建与现有方法同名的方法时。 要避免编译时错误, 必须使用与现有参数不同的参数定义新方法。 这样,方法将是可区分的。 有一个具有相同名称和参数的方法,但不同的返回类型仍然是模糊的,因此会导致编译错误。 重载示例:
class A { void bar(int i) {} // The following method is overloading the method bar void bar(Object a) {} // The following will cause a compile error. // Parameters should differ for valid overload boolean bar(int i) { return true; } }