【Java】Java对象的上转型对象与下转型

2023-05-16

Java对象的上转型对象与下转型

  • 1.解释说明
  • 2.代码示例
    • 2.1 示例一
    • 2.2 示例二
  • 3. 强制对象类型转换

将一个类型强制转换成另一个类型的过程被称为类型转换。
本节所说的对象类型转换,是指存在继承关系的对象,不是任意类型的对象。当对不存在继承关系的对象进行强制类型转换时,会抛出 Java 强制类型转换(java.lang.ClassCastException)异常。

1.解释说明

假设,A类是B类的父类,当用子类创建一个对象,并把这个对象的引用放到父类的对象中时,比如:

A  a;
a = new B();A a;
B  b = new B();
a = b;

这时,称对象a是对象b的上转型对象。
在这里插入图片描述

1.上转型对象不能操作子类新增的成员变量(失掉了这部分属性);不能调用子类新增的方法(失掉了一些功能)。
2.上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或子类的重写方法。上转型对象操作子类继承的方法或子类重写的方法,其作用等价于子类对象去调用这些方法。因此,如果子类重写了父类的某个方法后,当对象的上转型对象调用这个方法时一定是调用了子类重写的方法。

①不要将父类创建的对象和子类对象的上转型对象混淆。

②可以将对象的上转型对象再强制转换到一个子类对象,这时,该子类对象又具备了子类所有属性和功能。

③不可以将父类创建的对象的引用赋值给子类声明的对象

2.代码示例

2.1 示例一

public class Test {
    
    static class Anthropoid{
        double m=12.58;
        void crySpeak(String s){
            System.out.println(s);
        }
    }

    static class People extends Anthropoid{
        char m='A';
        int n=60;
        void compute(int a,int b){
            int c=a+b;
            System.out.println(a + "加" + b + "等于" + c);
        }
        @Override
        void crySpeak(String s){
            System.out.println(super.m + "**" + s + "**" + m);
        }
    }

    public static void main(String[] args) {
        People people=new People();
        // monkey是people的上转型对象
        Anthropoid monkey=people;
        // 等同于people调用重写的crySpeak方法
        monkey.crySpeak("A HAHA");

        // monkey.n=100;// 非法,n是子类新增的成员变量
        // monkey.computer(12,19);// 非法,子类新增的方法

        // 操作隐藏的m,不等同于people.m
        System.out.println(monkey.m);
        // 操作子类的m
        System.out.println(people.m);


        // 把上转型对象前置转换为子类对象
        People zhang=(People) monkey;
        zhang.compute(55,33);
        zhang.m='Z';
        System.out.println(zhang.m);
    }
}

结果:

12.58**A HAHA**A
12.58
A
55加33等于88
Z

2.2 示例二

public class Test2 {

    public static class Animal {
        public String name = "Animal:动物";
        public static String staticName = "Animal:可爱的动物";

        public void eat() {
            System.out.println("Animal:吃饭");
        }

        public static void staticEat() {
            System.out.println("Animal:动物在吃饭");
        }
    }

    public static class Cat extends Animal {
        public String name = "Cat:猫";
        public String str = "Cat:可爱的小猫";
        public static String staticName = "Dog:我是喵星人";

        @Override
        public void eat() {
            System.out.println("Cat:吃饭");
        }

        public static void staticEat() {
            System.out.println("Cat:猫在吃饭");
        }

        public void eatMethod() {
            System.out.println("Cat:猫喜欢吃鱼");
        }

        public static void main(String[] args) {
            Animal animal = new Cat();
            Cat cat = (Cat) animal; // 向下转型
            System.out.println(animal.name); // 输出Animal类的name变量
            System.out.println(animal.staticName); // 输出Animal类的staticName变量
            animal.eat(); // 输出Cat类的eat()方法
            animal.staticEat(); // 输出Animal类的staticEat()方法
            System.out.println(cat.str); // 调用Cat类的str变量
            cat.eatMethod(); // 调用Cat类的eatMethod()方法
        }
    }
}

结果:

Animal:动物
Animal:可爱的动物
Cat:吃饭
Animal:动物在吃饭
Cat:可爱的小猫
Cat:猫喜欢吃鱼

通过引用类型变量来访问所引用对象的属性和方法时,Java 虚拟机将采用以下绑定规则:

实例方法与引用变量实际引用的对象的方法进行绑定,这种绑定属于动态绑定,因为是在运行时由 Java 虚拟机动态决定的。例如,animal.eat() 是将 eat() 方法与 Cat 类绑定。
静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为是在编译阶段已经做了绑定。例如,animal.staticEat()是将 staticEat() 方法与 Animal 类进行绑定。
成员变量(包括静态变量和实例变量)与引用变量所声明的类型的成员变量绑定,这种绑定属于静态绑定,因为在编译阶段已经做了绑定。例如,animal.name和 animal.staticName 都是与 Animal 类进行绑定。

3. 强制对象类型转换

Java 编译器允许在具有直接或间接继承关系的类之间进行类型转换。
对于向下转型,必须进行强制类型转换;对于向上转型,不必使用强制类型转换。

例如,对于一个引用类型的变量,Java 编译器按照它声明的类型来处理。如果使用 animal 调用 str 和 eatMethod() 方法将会出错,如下:

animal.str = "";    // 编译出错,提示Animal类中没有str属性
animal.eatMethod();    // 编译出错,提示Animal类中没有eatMethod()方法

如果要访问 Cat 类的成员,必须通过强制类型转换,如下:

((Cat)animal).str = "";    // 编译成功
((Cat)animal).eatMethod();    // 编译成功

把 Animal 对象类型强制转换为 Cat 对象类型,这时上面两句编译成功。对于如下语句,由于使用了强制类型转换,所以也会编译成功,例如:

Cat cat = (Cat)animal;    // 编译成功,将Animal对象类型强制转换为Cat对象类型

类型强制转换时想运行成功就必须保证父类引用指向的对象一定是该子类对象,最好使用 instanceof 运算符判断后,再强转,例如:

Animal animal = new Cat();
if (animal instanceof Cat) {
    Cat cat = (Cat) animal; // 向下转型
    ...
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Java】Java对象的上转型对象与下转型 的相关文章

随机推荐

  • ROS 节点初始化步骤、topic/service创建及使用

    目录 1 节点初始化步骤 2 service 创建及使用 3 topic创建及使用 4 框架总结 这是一个总结复盘的记录 1 节点初始化步骤 在 mian 函数中使用 ros init 初始化节点 xff0c 注册节点名 xff0c 这里注
  • java 方法的注意事项

    方法的注意事项 1 方法不能嵌套定义 2 方法的返回值类型为void xff0c 表示该方法没有返回值 xff0c 没有返回值的方法可以省略return语句不写 xff0c 如果要编写return xff0c 后面不能跟具体的数据 3 re
  • java 方法重载

    方法名相同 xff0c 参数也完全相同 xff0c 称为方法的重复定义 xff0c 是一种冲突性的错误 如下 xff1a 在同一个类中 xff0c 定义了多个同名的方法 xff0c 但每个方法具有不同的参数或参数个数 xff0c 这些同名的
  • java 方法的参数传递(基本数据类型、引用数据类型)

    基本数据类型传递 xff1a span class token keyword public span span class token keyword class span span class token class name Test
  • java 方法求数组最大值

    需求 xff1a 设计一个方法用于获取数组中元素的最大值 xff1a span class token keyword public span span class token keyword class span span class t
  • docker 拉取镜像、创建并启动容器

    获取镜像 默认情况下 xff0c 使用docker pull命令 xff0c 会从官方的Docker Hub库中将镜像拉取到本地 首先介绍这条命令的格式 xff1a docker pull OPTIONS lt 仓库名 gt xff1a l
  • Docker 停止容器

    使用docker stop停止一个容器 docker stop可以用来终止一个正在运行的容器 它的命令格式如下 xff1a docker stop OPTIONS Container Container 其中 xff1a docker st
  • 进入docker容器

    进入docker容器的三种方法 1 使用ssh登陆进容器 xff1b 2 使用nsenter nsinit等第三方工具 xff1b 3 使用docker本身提供的工具 Docker目前主要提供了docker exec和docker atta
  • docker删除容器

    删除容器使用 docker rm 命令 xff1a 1 删除容器 1 首先需要停止所有的容器 docker stop docker ps a q 2 删除所有的容器 只删除单个时把后面的变量改为container id即可 docker r
  • docker 基于Commit定制镜像

    在Docker中提供了一个命令docker commit xff0c 该命令会把对容器的修改提交成一个镜像 换句话说 xff0c 就是在原有镜像的基础上 xff0c 再叠加上容器的存储层 xff08 该存储层仅仅保存了容器所做的修改 xff
  • Ubuntu 实现shell文件的开机运行(从原理到实现)

    目录 0 Linux的开机启动顺序 1 完善 rc local service 脚本 3 创建 rc local 脚本 4 总结 设置 shell 脚本开机启动的方法有挺多 xff0c 比如 xff1a 添加到 init d 中的方法 xf
  • docker 保存镜像、加载镜像

    将镜像保存到tar包 docker save用来将一个或者多个镜像保存为一个tar文件 xff0c 默认标准输出流的方式输出 xff0c 它的具体语法如下 xff1a docker save OPTIONS IMAGE IMAGE 其中 x
  • docker 导入导出容器

    将 容器的文件系统 保存到tar包 docker export是将 容器的文件系统 导出为一个tar包 注意是操作的对象是容器 xff01 它的具体语法如下 xff1a docker export OPTIONS CONTAINER 其中
  • docker 删除镜像

    删除镜像 如果要删除本地的镜像 xff0c 可以使用 docker rmi xff08 注意rm为删除容器 xff0c 而rmi为删除镜像 xff0c 其中i代表image xff09 命令 xff0c 它的具体语法如下 xff1a doc
  • docker 构建私有Registry、私人仓库

    1 使用docker tag给busybox加上一个标签localhost 5000 busybox latest xff1b docker tag busybox localhost span class token operator s
  • mall在linux环境下的部署(基于docker容器)

    mall在docker容器下部署涉及到MySQL Redis Nginx RabbitMQ MongoDB Elasticsearch Logstash Kibana xff0c 以及Spring Boot应用部署 本人事先已经拉取过镜像了
  • docker拉取镜像速度很慢的解决方法

    将docker修改为国内镜像源 在 etc docker daemon json文件中添加下面参数 xff0c 文件不存在的话创建即可 此处使用的是中国科技大学的docker镜像源 span class token punctuation
  • 解决您的qq.exe已在防护中,链接无法打开的问题

    适用于联想电脑 出现以上情况是由于默认了联想自带的浏览器打开QQ的链接 xff0c 如果不是直接点击的话可以复制到浏览器打开 xff0c 以下内容是方便直接QQ打开链接 问题如图 xff1a 解决方法 打开联想浏览器 设置 智能实验室 管理
  • ubunut16.04 kinetic版本gazebo7升级为gazebo9(完美解决!!!)

    问题 xff1a 我们加载gazebo7发现启动rourun节点有关摄像头的画面加载不出来 xff0c 往往是黑屏或者卡顿中断gazebo 原因 xff1a Gazebo版本太低造成的 因此 xff0c 需要对此升级 Kinetic中的默认
  • 【Java】Java对象的上转型对象与下转型

    Java对象的上转型对象与下转型 1 解释说明2 代码示例2 1 示例一2 2 示例二 3 强制对象类型转换 将一个类型强制转换成另一个类型的过程被称为类型转换 本节所说的对象类型转换 xff0c 是指存在继承关系的对象 xff0c 不是任