Java基础——多态、向上转型

一、多态:
1.定义:

         父类的引用指向子类的对象。

2.举例解读:
package com.qcby;

public class A {
    public String name;
    public int age;
    public void run(){
        System.out.println("A跑的很快");
    }
    public void eat(String name){
        System.out.println(name+ "吃的很多");
    }
}
--------------------------------------------
package com.qcby;

public class B extends A{
    public String sex;
    public double height;
    public void fly(){
        System.out.println("B飞得很高");
    }
    public void run(){
        System.out.println("B跑的很快");
    }
}

-----------------------------------------
package com.qcby;

public class Test {
    public static void main(String[] args) {
        A ab = new B();
        ab.name = "张三";
        ab.age = 18;
        ab.run();
        ab.eat("张三");
    }
}
-------------------------------------------
//运行结果:
//B跑的很快
//张三吃的很多

 父类:A      子类:B

此时,过程:

  1. 编译阶段

    • Test 类被编译成 Test.class
    • A 类被编译成 A.class
    • B 类被编译成 B.class,需要 A.class 的支持。
  2. 类加载阶段

    • A.class 和 B.class 被加载到方法区。
  3. 运行阶段

    • 创建 B 类型的对象,并将其赋值给 A 类型的变量 ab
    • 调用 ab.run(),由于 ab 实际上引用的是 B 类对象,因此调用 B 中的 run 方法。
    • 调用 ab.eat("张三"),由于 eat 方法在 A 类中定义且未在 B 类中重写,因此调用 A 类中的 eat 方法。

 内存图:标红是调用到的。

 3.多态的形式:

1. 方法重载:

       里面有方法的重载

2. 方法重写:

       里面有方法的重写

3. 接口实现和抽象类

       多态也可以通过接口和抽象类来实现。一个接口或抽象类定义了一组方法,但没有实现它们。具体的实现由实现接口或继承抽象类的子类提供。

例:

interface Shape {
    void draw();
}

class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a Circle");
    }
}

class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a Rectangle");
    }
}
abstract class Shape {
    abstract void draw();
}

class Circle extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a Circle");
    }
}

class Rectangle extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a Rectangle");
    }
}

 在这两个示例中,Shape 接口和 Shape 抽象类定义了 draw 方法,具体的实现由 CircleRectangle 提供。通过多态,代码可以处理不同类型的 Shape 对象,而无需关心具体的实现细节。

 二、向上转型:
1.基本概念:

         子类的对象可以被父类所接受,将一个子类对象引用赋值给其父类变量的过程。这是一种自动进行的类型转换,因为子类对象可以被看作是父类对象的一个实例。向上转型是一种常见的操作,特别是在使用多态时。

例:

package com.qcby;

public class A {
    public String name;
    public int age;
    public void run(){
        System.out.println("A跑的很快");
    }
    public void eat(String name){
        System.out.println(name+ "吃的很多");
    }
}

----------------------------------------------------
package com.qcby;

public class B extends A{
    public String sex;
    public double height;
    public void fly(){
        System.out.println("B飞得很高");
    }
    public void run(){
        System.out.println("B跑的很快");
    }
}
-----------------------------------------------------
package com.qcby;

public class C {
    public static void headler(A a) {
        System.out.println("C的输出。。。。。。。");
    }
}
--------------------------------------------------------
package com.qcby;

public class Test {
    public static void main(String[] args) {
        B b = new B();
        C.headler(b);
    }
}
-------------------------------------------------------
//运行结果:
//C的输出。。。。。。。

 由此可知,B的对象被A类所接受。

2.特点:

         1.自动转型:Java 在向上转型时会自动进行转换,程序员不需要显式地进行类型转换。

         2.访问权限:向上转型后,变量的类型是父类类型,因此只能访问父类中定义的方法和属性。子类特有的方法和属性在向上转型后无法访问。

         3.多态:向上转型使得 Java 的多态机制得以实现。即通过父类类型的引用,可以调用子类中重写的方法。这个特性在实现多态和设计灵活的系统时非常有用。

        4.安全性:向上转型是安全的。向上转型不会导致 ClassCastException 异常,但访问子类特有的方法会产生编译错误。

三、练习:
public class A {
    public String show(D obj) {
        return ("A and D");
    }
    public String show(A obj) {
        return ("A and A");
    } 
}

public class B extends A{
    public String show(B obj){
        return ("B and B");
    }
    
    public String show(A obj){
        return ("B and A");
    } 
}

public class C extends B{
}

public class D extends B{
}

public class Test {
    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(c));
        System.out.println("3--" + a1.show(d));
        
        System.out.println("4--" + a2.show(b));
        System.out.println("5--" + a2.show(c));
        System.out.println("6--" + a2.show(d));
        
        System.out.println("7--" + b.show(b));
        System.out.println("8--" + b.show(c));
        System.out.println("9--" + b.show(d));      
    }
}

输出结果:

  1. A and A
    解析:a1 调用的是 A 类中的方法,其中有 show(D)show(A) 两个重载方法。由于 b 被向上转型到 Aa1.show(b) 调用的是 A 类中的 show(A) 方法,输出 A and A。这在 a1A 类型,且 b 的类型向上转型的情况下是准确的。

  2. A and A
    解析:和第一个选项相似,a1 调用的是 A 类的方法,C继承于B,b 向上转型到 A,因此调用 show(A) 方法,输出 A and A。这个选项与第一个选项的解释相同。

  3. A and D
    解析:a1 调用的是 A 类的方法,其中有 show(D)show(A) 两个重载方法。如果 b 实际上是 D 类型,那么在 A 类中调用 show(D) 方法会输出 A and D

  4. B and A
    解析:a2B 类型,但由于方法重写,它调用的是 B 类中的 show(A) 方法。这个选项需要 B 类重写 A 类中的 show(A) 方法并且输出 B and A

  5. B and A
    解析:类似于第四个选项,a2B 类型,调用的是 B 类中的 show(A) 方法。这里需要 a2 向上转型到 A,调用 B 类的 show(A) 方法,输出 B and A

  6. A and D
    解析:与第三个选项相似,这个结果表明 a2 调用的是 A 类中的 show(D) 方法,输出 A and D。需要 b 实际上是 D 类型或其子类。

  7. B and B
    解析:bB 类型,B 类中的方法可以被调用,可能包括 show(D)show(A) 方法,这里输出 B and B。这表明 B 类中的方法重写了 A 类中的方法。

  8. B and B
    解析:和第七个选项类似,这个结果表明 bB 类型,由于继承和方法重写,输出 B and B

  9. A and D
    解析:bB 类型,调用了 A 类中的 show(D) 方法,输出 A and D。这表明 b 实际上是 D 类型或其子类,且重载方法选择为 show(D)

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值