Java 特性之多态性

case 3: 参数数据类型顺序变化(有效)

add(int, float)

add(float, int)

bad case 1: 仅改变返回类型(无效)

int add(int, int)

float add(int, int)

Java 方法签名由方法名和其后的参数列表共同决定,仅改变返回类型编译器无法重载。

方法重载(Method Overloading)允许改变返回类型和存取权限。

方法重载(Method Overloading)式多态性,即方法调用取决于调用时传递的参数(数量、类型、顺序),属于编译时静态多态性。

方法重写(Method Overriding)

方法重写(Method Overriding)允许子类对父类可以访问的方法,实现自定义行为。重写的优点在于,无需修改父类代码即可改变子类继承的方法。

重写形式:

重写依赖继承,通过父类引用,指向子类对象实现动态多态性。

public class Animal{

public void sound(){

System.out.println(“Animal is making a sound”);

}

}

public class Cat extends Animal{

@Override

public void sound(){

System.out.println(“Meow”);

}

public static void main(String args[]){

Animal obj = new Cat();

obj.sound();

}

}

输出:

Meow

重写(覆盖)规则

  • 参数列表必须一样,返回类型需要兼容。

  • 不能降低方法的存取权限。

  • static, private, final 标记的方法以及类的构造方法不能被重写覆盖。

静态绑定与动态绑定


多态的类型可以分为运行时和编译时,方法重写(Method Overriding)代表运行时动态多态性,方法重载(Method Overloading)代表编译时静态多态性。

方法调用与方法体的关联称为绑定,有两种类型的绑定:在编译时发生的静态绑定(Static Binding or Early Binding)和在运行时发生的动态绑定(Dynamic Binding or Late Binding)。

static, private, final 标记的方法以及类的构造方法是编译时静态绑定的。因为此类方法无法覆盖,并且类的类型在编译时即可确定。其他非标记的方法可以称为“虚函数”,Java 中其实并没有“虚函数”的概念,所有普通函数(方法)默认都相当于 C++ 的”虚函数”允许覆盖(Override),因此虚函数(virtual method)能够根据运行时的具体对象进行动态绑定实现动态多态性,例如方法重写(Method Overriding)。

静态绑定示例:

class Human{

public static void walk()

{

System.out.println(“Human walks”);

}

}

class Boy extends Human{

public static void walk(){

System.out.println(“Boy walks”);

}

public static void main( String args[]) {

/* Reference is of Human type and object is

  • Boy type

*/

Human obj = new Boy();

/* Reference is of Human type and object is

  • of Human type.

*/

Human obj2 = new Human();

obj.walk();

obj2.walk();

}

}

输出:

Human walks

Human walks

声明为 static 的方法不能被重写,但是能够被再次声明。

Static Binding vs Dynamic Binding

  • 静态绑定发生在编译时,而动态绑定发生在运行时。

  • 静态绑定使用的是类信息:类的类型决定调用方法,而动态绑定使用的是对象信息:对象的类型决定调用方法。

  • 方法重载使用静态绑定,而方法重写使用动态绑定。

综合练习


多态示例:

class A {

public String show(D obj) { // 方法一

return (“A and D”);

}

public String show(A obj) { // 方法二

return (“A and A”);

}

}

class B extends A {

public String show(B obj) { // 方法三

return (“B and B”);

}

public String show(A obj) { // 方法四

return (“B and A”);

}

}

class C extends B {

}

class D extends B {

}

public class Main {

public static void main(String[] args) {

A a1 = new A();

A a2 = new B();

B b = new B();

C c = new C();

D d = new D();

System.out.println(“1–” + a1.show(b));

System.out.println(“2–” + a1.show©);

System.out.println(“3–” + a1.show(d));

System.out.println(“4–” + a2.show(b));

System.out.println(“5–” + a2.show©);

System.out.println(“6–” + a2.show(d));

System.out.println(“7–” + b.show(b));

System.out.println(“8–” + b.show©);

System.out.println(“9–” + b.show(d));

}

}

运行结果:

1–A and A

2–A and A

3–A and D

4–B and A

5–B and A

6–A and D

7–B and B

8–B and B

9–A and D

详细分析:

A、B、C、D 各类继承关系如图所示:

类图

  1. A a1 = new A(); 正常创建对象 a1,涉及函数重载 show(),a1 具有调用方法一 show(D obj) 和方法二 show(A obj) 的能力。

a1.show(b) 由编译器进行静态绑定(前期绑定)方法二 show(A obj)。

  1. a1.show(c) 由编译器进行静态绑定(前期绑定)方法二 show(A obj)。

  2. a1.show(d) 由编译器进行静态绑定(前期绑定)方法一 show(D obj)。

8–B and B

9–A and D

详细分析:

A、B、C、D 各类继承关系如图所示:

[外链图片转存中…(img-cgXmLc2T-1727477654367)]

  1. A a1 = new A(); 正常创建对象 a1,涉及函数重载 show(),a1 具有调用方法一 show(D obj) 和方法二 show(A obj) 的能力。

a1.show(b) 由编译器进行静态绑定(前期绑定)方法二 show(A obj)。

  1. a1.show(c) 由编译器进行静态绑定(前期绑定)方法二 show(A obj)。

  2. a1.show(d) 由编译器进行静态绑定(前期绑定)方法一 show(D obj)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值