强制类型转换

news2024/11/17 19:39:28

问题

最近在研读公司项目的时候发现一段很有意思的代码:

if (a instanceof b) {
    B ent = (B) a;
    if (!useGivenAuditAttributes) {
        ent.createdAt = MyDateUtils.now();
        ent.createdBy = AppContext.instance.loginUser.userId;
        ent.lastUpdatedAt = ent.createdAt;
        ent.lastUpdatedBy = ent.createdBy;
    }
}

后续并没有对ent对象进行操作,在 if 块结束后,它的作用域就结束了。因此,从表面上看,这个变量会被销毁,后续代码无法直接访问这个局部变量。

那么这段代码有什么作用呢?

查阅资料之后我发现了一个被遗忘的知识点。

解析

先说结论

ent 虽然是局部变量,但它本质上引用的是 a对象,这意味着对 ent 的修改实际上是在修改 a对象本身。

ent 在 if 块内被销毁只是引用被销毁,它指向的 a对象本身并不会被销毁。ent 对 a属性的修改是直接作用在 a对象上的,因此,后续代码依然能访问这些修改过的属性。

 是不是很疑惑?如果不疑惑说明你很强!

首先总所周知的是,在 Java 中,对象引用是指一个变量存储了对象在内存中的地址,而不是对象本身。

在 Java 中,类的实例(对象)存在于内存中,而引用类型的变量(如 B entT a,这里的T代表泛型)则存在于内存中,它们存储的是指向堆中实际对象的引用(即对象的内存地址)。

其次我们要知道,java当中强制类型转换的原理

当执行 B ent = (B) a; 时:

  • 编译时检查: 编译器会验证 a的静态类型是否可以被转换为 B类型。因为 a的实际类型是A,即 B 的子类,所以这个转换在编译时是合法的。
  • 运行时转换: 在运行时,JVM 会检查 a的实际类型,并将 a的引用(指向堆中对象的地址)赋值给 ent。注意,这里的转换只是更改了引用的静态类型(ent 是 B类型),而堆中对象本身并没有发生改变。

因此在类型转换后,变量 ent 和 a都存储了相同的内存地址,因此它们指向同一个对象,即堆中相同的 A实例。

内存中即为这样:

因为 ent 和 a都指向同一个对象,所以通过 ent 修改该对象的属性会影响到 a对象。

实例

下面上代码


public class A {
    private String name;

    public A(String name) {
        this.name = name;
    }

    public A() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


public class B extends A{
    private int age;

    public B(String name, int age) {
        super(name);
        this.age = age;
    }

    public B(int age) {
        this.age = age;
    }

    public B(String name) {
        super(name);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

 public static void main(String[] args) {
        B b = new B("jack", 10);
        A a = (A) b;
        System.out.println(a.getName());
        a.setName("vivian");
        System.out.println(b.getName());
    }

运行截图如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2162577.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何把python(.py或.ipynb)文件打包成可运行的.exe文件?

将 Python 程序打包成可执行的 .exe 文件,通常使用工具如 PyInstaller。这是一个常用的 Python 打包工具,可以将 Python 程序打包成独立的可执行文件,即使没有安装 Python 也能运行。 步骤: 1. 安装 PyInstaller 使用 conda 安…

【shell脚本5】Shell脚本学习--条件控制

目录 条件判断:if语句 分支控制:case语句 条件判断:if语句 语法格式: if [ expression ] thenStatement(s) to be executed if expression is true fi 注意:expression 和方括号([ ])之间必须有空格,否…

centos7 配置 docker 国内镜像源

1.修改配置文件/etc/docker/daemon.json sudo vim /etc/docker/daemon.json2.增加或修改以下配置内容 {"registry-mirrors": ["https://dockerproxy.com","https://hub-mirror.c.163.com","https://mirror.baidubce.com","http…

谷歌浏览器如何更改下载文件存放的方式及其路径?

1、点击谷歌浏览器右上角的【三个点】 2、选择【设置】,再选择【下载内容】 3、打开【下载完成后显示下载内容】开关, 则:下载网页上的东西之后,会显示在【谷歌浏览器】的右侧,并显示具体下载文件在右侧:…

PR视频剪辑工具全指南:开启专业剪辑之旅

pr视频剪辑可以说是视频剪辑里的一把好手,就是如果你想在这方面深耕那还是掌握这个工具的使用比较方便。如果你只是刚入门,那也有不少可以快速帮你剪辑出片的工具。这次我介绍几款我用过的视频剪辑工具,助你开启视频剪辑大门。 1.福昕视频剪…

vue echarts tooltip动态绑定模板,并且处理vue事件绑定

先上代码: tooltip: {// 这里是车辆iconshow: true,// trigger: "item",// backgroundColor: "transparent",appendToBody: true,textStyle: {color: "#ffffff" //设置文字颜色},formatter: (params) > {const TruckTooltip Vue.…

Java-数据结构-排序(三) |ू・ω・` )

目录 ❄️一、归并排序: ☞ 基本思想: ☞ 代码: ☞ 归并排序的非递归方法: ❄️二、排序算法的分析: ❄️三、非基于比较的排序: ❄️总结: ❄️一、归并排序: ☞ 基本思想&#xf…

在一个.NET Core项目中使用RabbitMQ进行即时消息管理

为了在一个.NET Core项目中使用RabbitMQ进行即时消息管理,以下是详细的全程操作指南,包括安装、配置、编写代码和调试使用。 一、安装RabbitMQ 1. 安装Erlang RabbitMQ依赖Erlang,因此需要先安装Erlang。 Windows: 下载并运行Erlang安装…

人工智能-机器学习-深度学习-分类与算法梳理

目前人工智能的概念层出不穷,容易搞混,理清脉络,有益新知识入脑。 为便于梳理,本文只有提纲,且笔者准备仓促,敬请勘误,不甚感激。 请看右边目录索引 。 人工智能 三大派系 符号主义(Symbolists…

[附源码]宠物领养管理系统+SpringBoot

今天带来一款优秀的项目:宠物领养管理系统源码 。 系统采用的流行的前后端分离结构,内含功能包括"管理端",“用户领养端”,“宠物管理”,“权限登录”等功能。 如果您有任何问题,也请联系小编&a…

keepalived+lvs集群

目录 一、环境 二、配置 1、master 1.在master上安装配置Keepalived 2.在master上修改配置文件 2、backup 1.在backup(192.168.229.12)上安装keepalived 2.在backup上修改配置文件 3、master和backup上启动服务 4、web服务器配置 1.web1和web…

使用Java基于GeoTools读取Shapefile矢量数据属性信息-以某市POI数据为例

前言 在之前的博客中,我们讲过在GDAL中如何读取空间数据的属性和数据信息,也简单的讲过如何在GeoTools中读取Shapefile文件的属性信息和数据信息。对于空间矢量数据库,就像我们传统的二维数据库的表字段和表数据的关系,在研究表数…

BERT训练之数据集处理(代码实现)

目录 1读取文件数据 2.生成下一句预测任务的数据 3.预测下一个句子 4.生成遮蔽语言模型任务的数据 5.从词元中得到遮掩的数据 6.将文本转化为预训练数据集 7.封装函数类 8.调用 import os import random import torch import dltools 1读取文件数据 def _read_wiki(data_d…

Java框架学习(Spring)(ioc)(01)

简介:以本片记录在尚硅谷学习ssm-spring-ioc时遇到的小知识 详情移步:想参考的朋友建议全部打开相互配合学习! 视频: 014-spring-框架概念理解_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1AP411s7D7?p14&vd_sou…

SpringBoot框架在文档管理中的创新应用

第3章 系统分析 3.1 需求分析 在线文档管理系统主要是为了提高工作人员的工作效率和更方便快捷的满足员工,更好存储所有数据信息及快速方便的检索功能,对系统的各个模块是通过许多今天的发达系统做出合理的分析来确定考虑员工的可操作性,遵循…

峟思助力堤防工程安全:构建多功能防洪屏障

堤防工程,作为水利建设中至关重要的防护体系,不仅守护着江河、湖泊及滨海区域的安全,更是确保人民生命财产安全的坚固防线。在现代社会,随着技术的进步与安全意识的提升,堤防工程不仅限于传统的防洪功能,更…

SpringBoot和JPA初探

目录 SpringBoot和JPA初探0.准备条件1.创建JPA项目2.项目3.总结 SpringBoot和JPA初探 我们使用SpringBootJPA做一个简单的API接口演示,通过一个简单的例子让大家对Spring Data JPA有一个整体的认知。 0.准备条件 IntelliJ IDEAjdk 1.8mysql 8.0maven 3.8.x 1.创…

代码随想录算法训练营第三十九天 | 198.打家劫舍 ,213.打家劫舍II,337.打家劫舍III

第三十九天打卡,今天解决打家劫舍系列问题,树形dp比较难。 198.打家劫舍 题目链接 解题过程 dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]。 要么不偷这一间,那就是前面那间…

开源链动 2+1 模式、AI 智能名片与 S2B2C 商城小程序:以问题解决为导向的盈利新模式

摘要:本文探讨了问题解决盈利模式的重要性,并结合开源链动 21 模式、AI 智能名片以及 S2B2C 商城小程序等创新工具,阐述了如何以用户为中心,通过深刻洞察用户需求,解决用户问题,实现盈利增长。强调了在当今…

[利用python进行数据分析01] “来⾃Bitly的USA.gov数据” 分析出各个地区的 windows和非windows用户

2011 年, URL 缩短服务 Bitly 跟美国政府⽹站 USA.gov 合作,提供 了⼀份从⽣成 .gov 或 .mil 短链接的⽤户那⾥收集来的匿名数据。 在 2011 年,除实时数据之外,还可以下载⽂本⽂件形式的每⼩时 快照。 数据集下载:通…