向上转型和向下转型的实例

package musical;

public class instrument {
    public void makeSound(){
        System.out.println("乐器可以演奏!");
    }
}

package musical;

public class Erhu extends instrument{
    @Override
    public void makeSound() {
        System.out.println("乐手正在演奏二胡!");
    }
    public  void like(){
        System.out.println("样子像一个弓箭!");
    }
}

package musical;

public class Piano extends  instrument {
    @Override
    public void makeSound() {
        System.out.println("乐手正在演奏钢琴!");
    }
    public  void like(){
        System.out.println("样子像一个机器!");
    }
}

package musical;

public class Violin extends instrument {
    @Override
    public void makeSound() {
        System.out.println("乐手正在演奏小提琴!");
    }
    public  void like(){
        System.out.println("样子像一个葫芦!");
    }
}
package musical;

public class Musician {
    instrument i;
    public Musician(instrument instrument){
        this.i = instrument;
    }
     public void play(){
        i.makeSound();

     }

     public void lookLike(){
        if(i instanceof Erhu){//instance,可以在程序运行
            // 阶段判断某个引用指向的对象是否为某一类型,
            // 向下转型一定要判断类型,这是企业的代码规范。
//            ((Erhu) i).like();
            Erhu erhu = (Erhu)i;
            erhu.like();
        }
        if(i instanceof Violin){
            Violin violin = (Violin) this.i;
            violin.like();
        }
        if (i instanceof Piano){
            Piano piano = (Piano)i;
            piano.like();
        }
     }
}
package musical;

public class Test {
    public static void main(String[] args) {
        //子转父
        instrument i = new Violin();//向上转型(自然转换),可理解为小提琴是一个乐器
        i.makeSound();

        //父转子,向下转型(强制转换),需要子类中有特有的方法时,才可以编译
         instrument ii = new Piano();
         ((Piano)ii).like();
         Piano p = (Piano)ii;
         p.like();

         
        Musician musician = new Musician(new Erhu());
        musician.play();
        musician.lookLike();


    }
}

结果:
在这里插入图片描述
若有问题,请指教!

<think>嗯,用户想了解向上转型向下转型的存储原理。首先,我得回忆一下面向对象编程中的这两个概念。向上转型向下转型通常与继承多态相关,尤其是在Java这样的语言里。用户可能已经对继承多态有基本了解,但需要深入理解转型时内存中的变化。 首先,向上转型(Upcasting)是指将子类对象赋值给父类引用。比如,假设有一个父类Animal一个子类Dog,那么Dog dog = new Dog(); Animal animal = dog; 这里发生了向上转型。这时候,父类引用animal指向的是子类对象Dog的实例。存储方面,子类对象在内存中包含了父类的所有属性方法,以及子类特有的部分。当向上转型后,父类引用只能访问父类中定义的成员,而子类特有的成员会被隐藏,但实际对象在内存中的结构并没有改变。这类似于“视角”的转换,引用类型限制了访问范围,但对象本身还是完整的。 接下来是向下转型(Downcasting),即把父类引用转换为子类引用。例如,Animal animal = new Dog(); Dog dog = (Dog) animal; 这里需要显式转换,并且运行时实际对象必须是目标类型或其子类,否则会抛出ClassCastException。存储方面,向下转型是否安全取决于实际对象类型。如果animal实际指向的是Dog实例,那么转换是安全的,此时dog引用可以访问Dog特有的成员。但如果animal实际指向的是其他子类比如Cat,那么转换就会失败。 这里可能需要解释类型检查机制,比如Java中的instanceof操作符,用于在向下转型前检查类型,确保安全。存储方面,父类引用虽然存储了子类对象的所有信息,但在编译时编译器只根据引用类型检查访问权限,因此向下转型时需要显式告知编译器,允许访问子类特有的部分。 用户可能存在的疑问是:为什么向上转型是安全的,而向下转型需要显式转换检查?因为在向上转型中,子类必定包含父类的所有属性方法,所以转换不会丢失信息,只是限制了访问范围。而向下转型可能访问到父类引用实际对象没有的成员,因此需要确保类型匹配。 另外,存储原理涉及到对象在内存中的布局。每个对象在堆中存储时,会包含类型信息(比如虚方法表),这使得运行时类型检查(RTTI)成为可能。当向下转型时,JVM会检查对象的实际类型是否符合目标类型,从而保证类型安全。 总结起来,向上转型向下转型的核心在于引用类型实际对象类型的关系,以及内存中对象的完整信息存储。向上转型是隐式的、安全的,而向下转型需要显式并可能引发运行时错误,因此需要谨慎处理。</think>以下分步骤解释向上转型(Upcasting)向下转型(Downcasting)的存储原理: --- ### **一、基本概念** - **向上转型**:子类对象赋值给父类引用(自动完成,无需强制转换) - **向下转型**:父类引用强制转回子类引用(需显式类型转换) --- ### **二、存储原理** #### **1. 对象内存结构** 所有对象在堆内存中存储时包含: - **类型标识信息**(如Java的Class对象指针) - **父类成员变量** - **子类特有成员变量** 示例: ```java class Animal { int a; } class Dog extends Animal { int b; } Dog dog = new Dog(); // 内存包含Animal的aDog的b ``` #### **2. 向上转型时的存储** - **操作**:`Animal animal = dog;` - **原理**: - 父类引用`animal`指向子类对象的内存地址 - 通过父类引用只能访问父类成员(`a`),但子类数据(`b`)仍存在于内存中 - **内存结构未改变**,只是访问权限受限 ```java animal.a = 10; // 合法操作 // animal.b = 20; // 编译报错:父类引用无法访问子类成员 ``` #### **3. 向下转型时的存储** - **操作**:`Dog newDog = (Dog) animal;` - **原理**: 1. 编译器检查语法合法性 2. **运行时校验**:JVM检查实际对象类型是否匹配目标类型 3. 若类型匹配,恢复对子类成员的访问权限 ```java if (animal instanceof Dog) { Dog newDog = (Dog) animal; newDog.b = 20; // 合法操作:访问子类特有成员 } ``` --- ### **三、关键区别** | 特性 | 向上转型 | 向下转型 | |--------------|-------------------------|---------------------------| | **安全性** | 绝对安全(子类→父类) | 需运行时校验(可能失败) | | **内存变化** | 无 | 无 | | **访问范围** | 缩小到父类成员 | 恢复到子类完整成员 | --- ### **四、本质总结** - **存储始终完整**:无论转型如何操作,对象内存始终保存完整数据 - **引用类型决定访问范围**:转型仅改变编译器对内存的“解读方式”,不影响实际存储 - **向下转型风险**:若实际对象类型不匹配,会抛出`ClassCastException` --- ### **五、示例验证** ```java Animal animal = new Dog(); // 向上转型 animal.a = 10; // 修改父类成员 Dog dog = (Dog) animal; // 向下转型(安全) System.out.println(dog.b); // 输出子类成员默认值0 ``` 通过理解存储原理,可避免因类型转换导致的逻辑错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值