true or false?

news2024/11/28 4:26:49

有同学在星球问了这样一个问题。

12257a1964ec025c9eb6cb5d436c87dd.png

代码是这样的:

public class Main {
    private static final Main instance = new Main();
    private boolean b = a;
    private static  boolean a = initA();

    private static boolean c = a;

    private static boolean initA() {
        return true;
    }

    private static boolean getC() {
        return c;
    }

    public static void main(String[] args) {
        System.out.println(instance.b + " " + getC());
    }
}

最后的输出结果你以为是 true true,其实是 false true。

GPT 表示对于这个问题,他确实无法理解。。。

为了看这个问题的结果,可以反编译看下,执行命令:

javac Main.java
javap -c Main

得到反编译的字节码结果,结果包含 3 个部分:

  1. 1. public com.aixiaoxian.orm.Main() 调用无参构造函数

  2. 2. public static void main(java.lang.String[]); main 方法

  3. 3. static{} 静态代码

看静态代码部分赋值,13、16 、19,可以很明显的发现 c 和 a 的值都是 true。

然后再看 8 和 6,取值是索引 13 的位置,并没有初始化,所以值应该默认是 false。

Compiled from "Main.java"
public class com.aixiaoxian.orm.Main {
  public com.aixiaoxian.orm.Main();
    Code:
       0: aload_0 //将当前对象的引用(this)压入操作数栈。
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V 调用构造函数
       4: aload_0 // 再次将当前对象的引用(this)压入操作数栈。
       5: getstatic     #7                  // Field a:Z //获取静态变量a的值,并将其压入操作数栈中。
       8: putfield      #13                 // Field b:Z // 将操作数栈顶的值赋给成员变量b。
      11: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #19                 // Field java/lang/System.out:Ljava/io/PrintStream; 获取System.out静态变量
       3: getstatic     #25                 // Field instance:Lcom/aixiaoxian/orm/Main; 获取Main类的静态变量instance
       6: getfield      #13                 // Field b:Z 将instance对象的成员变量b的值(布尔型)压入操作数栈 
       9: invokestatic  #29                 // Method getC:()Z 调用getC()方法
      12: invokedynamic #33,  0             // InvokeDynamic #0:makeConcatWithConstants:(ZZ)Ljava/lang/String; 动态调用makeConcatWithConstants()方法
      17: invokevirtual #37                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 调用PrintStream.println()方法
      20: return

  static {};
    Code:
       0: new           #8                  // class com/aixiaoxian/orm/Main 创建Main类的新实例
       3: dup: //复制对象引用,将新实例的引用压入操作数栈
       4: invokespecial #43                 // Method "<init>":()V 调用Main类的构造方法
       7: putstatic     #25                 // Field instance:Lcom/aixiaoxian/orm/Main; 给instance静态变量赋值,将栈顶元素存储在instance中
      10: invokestatic  #44                 // Method initA:()Z 调用initA()方法
      13: putstatic     #7                  // Field a:Z 给a静态变量赋值
      16: getstatic     #7                  // Field a:Z 获取a静态变量的值,将其压入操作数栈。
      19: putstatic     #16                 // Field c:Z 给c静态变量赋值,将栈顶元素(即a的值)存储在c中。
      22: return
}

那么问题是为什么 b 在初始化的时候为什么没有把 a 的值赋给他呢?

看这个问题我们先复习一下 new 对象的过程。

f2f79f3386f9f3dd062047038969f243.jpeg

当虚拟机遇见new关键字时候,实现判断当前类是否已经加载,如果类没有加载,首先执行类的加载机制,加载完成后再为对象分配空间、初始化等。

  1. 1. 首先校验当前类是否被加载,如果没有加载,执行类加载机制

  2. 2. 加载:就是从字节码加载成二进制流的过程

  3. 3. 验证:当然加载完成之后,当然需要校验Class文件是否符合虚拟机规范,跟我们接口请求一样,第一件事情当然是先做个参数校验了

  4. 4. 准备:为静态变量、常量赋默认值

  5. 5. 解析:把常量池中符号引用(以符号描述引用的目标)替换为直接引用(指向目标的指针或者句柄等)的过程

  6. 6. 初始化:执行static代码块(cinit)进行初始化,如果存在父类,先对父类进行初始化

当类加载完成之后,紧接着就是对象分配内存空间和初始化的过程

  1. 1. 首先为对象分配合适大小的内存空间

  2. 2. 接着为实例变量赋默认值

  3. 3. 设置对象的头信息,对象hash码、GC分代年龄、元数据信息等

  4. 4. 执行构造函数(init)初始化

在这个代码中,首先先要执行类的初始化,类初始化过程中去给静态变量、常量赋值,之后再去给实例变量赋值,按照道理来说 b 应该也是 true 才对。

问题其实出现在代码顺序上,第一行代码就是去 new 一个静态的 Main 实例对象,但是这里代码顺序先去初始化 instance ,但是此时代码 a 的定义写在 instance 之后,所以初始化 instance 对象的时候其实 a 还没有赋值,所以给 b 赋值的时候就是 false。

所以这里的代码只要调整一下顺序,把private static boolean a = initA();放到第一行,结果就会变成 true 了。

好了好了,就这样,都散了吧。

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

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

相关文章

洛谷B2099 矩阵交换行

矩阵交换行 题目描述 给定一个 5 5 5 \times 5 55 的矩阵(数学上&#xff0c;一个 r c r \times c rc 的矩阵是一个由 r r r 行 c c c 列元素排列成的矩形阵列)&#xff0c;将第 n n n 行和第 m m m 行交换&#xff0c;输出交换后的结果。 输入格式 输入共 6 6 6 …

DataEase 本地源码启动详细教程

本教程将引导你通过本地源码部署的方式启动 DataEase&#xff0c;同时我还录制了相应的视频教程&#xff0c;你可以跟随视频进行操作&#xff1a; DataEase 本地源码启动_哔哩哔哩_bilibili 1、下载并安装IDEA开发工具 2、下载安装Mysql 5.7 以及 JDK 1.8 如果你使用的是wi…

使用pdf.js展示pdf文件(亲测可用)

简单的实现方式 如果只是电脑端&#xff0c;可通过 iframe 标签嵌套预览 ios手机端可通过 a 标签包裹点击跳转预览&#xff08;安卓端不行&#xff09; 安卓电脑ios的通用方法 资料 老版本github地址 全版本地址 获取当前客户端类型 judgeClient() {let client if (/(iPh…

鲁大师智能化评测新项目——鲁大师真续航测试1.0正式发布

随着社会的高速发展&#xff0c;人们出行的交通工具正变得多种多样&#xff0c;有电单车、摩托车、自行车、两轮平衡车、甚至滑板等。不过如我们所见&#xff0c;电动两轮车已经成为了大多数近途出行用户的选择&#xff0c;因电单车具有方便、快捷、灵活、小巧、易停放等优点而…

MySQL基础篇4

MySQL基础 1. 数据类型1.1 整数类型1.2 浮点类型1.3 定点数类型1.4 位类型1.5 日期时间类型1.6 文本字符串类型1.6.1 CHAR类型和VARCHAR类型1.6.2 TEXT类型 1.7 ENUM枚举类型1.8 SET类型1.9 二进制字符串类型1.10 JSON数据类型 2. 约束2.1 前置知识2.1.1 为什么需要约束2.1.2 约…

亚马逊云科技围绕需求发力,赋能医疗与生命科学行业数字化创新

2023年4月27日&#xff0c;亚马逊云科技医疗与生命科学行业峰会召开&#xff0c;会议汇聚了业界专家和思想领袖&#xff0c;共同探讨行业数字化转型和创新之道。作为全球医疗及生命科学行业云计算引领者&#xff0c;亚马逊云科技将围绕数据、算力和行业用户体验三大需求发力&am…

移远“5G+Wi-Fi 6”方案双重加速,为用户带来更具性价比的连网体验

近年来&#xff0c;人们对于高速宽带连接的需求猛增&#xff0c;这对网络传输速率、稳定性与时延都提出了更高的要求。在离开网络寸步难行的今天&#xff0c;插电即用、免拉宽带的5G CPE受到了广泛关注。 在地广人稀的部分海外市场&#xff0c;受制于光纤铺设成本、周期、路由规…

Day966.从组件团队到Spotify模型 -遗留系统现代化实战

从组件团队到Spotify模型 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于从组件团队到Spotify模型的内容。 团队结构现代化。这个方向跟管理有关&#xff0c;但无论掌控全局的 CTO、架构师&#xff0c;还是身处遗留系统一线战队的队员&#xff0c;都有必要了解现代…

JavaScript - 基础+WebAPI(笔记)

前言&#xff1a; 求关注&#x1f62d; 本篇文章主要记录以下几部分&#xff1a; 基础&#xff1a; 输入输出语法&#xff1b;数据类型&#xff1b;运算符&#xff1b;流程控制 - 分支语句&#xff1b;流程控制 - 循环语句&#xff1b;数组 - 基础&#xff1b;函数 - 基础&…

idm下载器2024官方最新中文版免费下载

哈喽大家好呀&#xff0c;coco玛奇朵发现我已经有一阵子没有给大家分享windows软件了&#xff0c;今天给大家分享一款暗藏惊喜的windows软件&#xff0c;用过之后真的很难拒绝&#xff01; 这是一个可以帮你提升下载速度的工具&#xff0c;有了它几秒就能帮你下载好各种资源。…

UNIAPP实战项目笔记64 当前用户修改收货地址的前端和后端

UNIAPP实战项目笔记64 当前用户修改收货地址的前端和后端 思路 默认地址的修改&#xff0c;先清空当前id下的所有默认地址&#xff0c;再将新地址设为默认 前端 将新值传给后端 后端接受值后更新处理 实例截图 代码 后端 index.js var express require(express); var route…

大数据Doris(十六):分桶Bucket和分区、分桶数量和数据量的建议

文章目录 分桶Bucket和分区、分桶数量和数据量的建议 一、分桶Bucket

机器学习随记(6)—K-means

1 K-means方案 K-means 算法是一种自动将相似数据点聚集在一起的方法。 具体来说&#xff0c;你得到了一个训练集{,...,}&#xff0c;并且您希望将数据分组为几个有凝聚力的“集群”。 K-means 是一个迭代过程 首先猜测初始质心&#xff0c;然后改进这个猜测 反复将样本分配到…

Seurat -- Cluster the cells --第一部分

文章目录 briefKNN&#xff08;k-nearest neighbor&#xff09;简介部分SNN&#xff08;shared nearest neighbor&#xff09;简介部分Annoy算法理解Jaccard indexSeurat进行聚类的步骤可视化部分subcluster之间的marker gene具体参数 brief seurat 官方教程的解释如下&#x…

Hash碰撞

Hash碰撞 什么是Hash碰撞 Hash碰撞是指两个不同的输入值&#xff0c;经过哈希函数的处理后&#xff0c;得到相同的输出值&#xff0c;这种情况被称之为哈希碰撞。 例如&#xff1a;两个不同的对象&#xff08;object1和object2的值&#xff09;经过Hash函数计算后的&#xf…

科思转债上市价格预测

科思转债 基本信息 转债名称&#xff1a;科思转债&#xff0c;评级&#xff1a;AA-&#xff0c;发行规模&#xff1a;7.249178亿元。 正股名称&#xff1a;科思股份&#xff0c;今日收盘价&#xff1a;67.1元&#xff0c;转股价格&#xff1a;53.03元。 当前转股价值 转债面值…

【进程间通信 之 通信的建立】

目录&#xff1a; 前言进程间通信的目的进程间通信的方式管道1.匿名管道简单示例1 - 消息传输五个特性四种场景简单示例2 - 进程控制对管道的深入理解 2.命名管道简单示例3 -- 不相关进程间通信 system V共享内存简单示例4 - 通知事件消息传输 总结 前言 打怪升级&#xff1a;…

后摩尔时代 , 从有源相控阵天线走向天线阵列微系统

本文围绕高分辨率对地微波成像雷达对天线高效率、低剖面和轻量化的迫切需求 , 分析研究了有源阵列天线的特点、现状、趋势和瓶颈技术 , 针对对集成电路后摩尔时代的发展预测 , 提出了天线阵列微系统概念、内涵和若干前沿科学技术问题 , 分析讨论了天线阵列微系统所涉及的微纳尺…

完全集成的云备份和还原服务——NetApp Cloud Backup

完全集成的云备份和还原服务 NetApp Cloud Backup 提供无缝且经济高效的备份和还原功能&#xff0c;用于保护和归档云端和内部 ONTAP 数据。 为什么选择 NetApp Cloud Backup&#xff1f; 可轻松保护云端和内部 ONTAP 数据 NetApp Cloud Backup 提供无缝且经济高效的备份和还…

科大讯飞星火认知大模型怎么样?

“鉴于SparkDesk服务目前处于内部用户体验阶段&#xff0c;所有与SparkDesk相关的交互内容、技术参数等信息均被视为保密信息。您了解并同意&#xff0c;且有责任对这些保密信息严格保密&#xff0c;您不得以任何方式&#xff08;包括但不限于截图、录屏、拍照等&#xff09;披…