当前位置: 首页 > news >正文

java常量和kotlin常量

  • java中使用final声明常量
  • kotlin中使用const val声明常量

常量在编译为字节码后会直接把调用常量的地方直接替换为常量值,示例如下:

public class ConstDemo {public static final String NAME = "Even";private static final int ID = 1001;static final int YEAR = 2024;public final int color = 255;public static int width = 100;public int height = 200;public static void main(String[] args) {System.out.println(NAME);System.out.println(NAME);System.out.println(ID);System.out.println(ID);System.out.println(YEAR);System.out.println(YEAR);ConstDemo demo = new ConstDemo();System.out.println(demo.color);System.out.println(demo.color);final int number = 9;System.out.println(number);System.out.println(number);System.out.println("--------------------------------");final int count;if (width > 100) {count = 1;} else {count = 2;}System.out.println(count);System.out.println(count);System.out.println(width);System.out.println(width);System.out.println(demo.height);System.out.println(demo.height);int weight = 99;System.out.println(weight);System.out.println(weight);}}

编译后得到class字节码,在IntelliJ中可以直接双击这个class字节码,它是自带反编译器,效果如下:

public class ConstDemo {public static final String NAME = "Even";private static final int ID = 1001;static final int YEAR = 2024;public final int color = 255;public static int width = 100;public int height = 200;public ConstDemo() {}public static void main(String[] args) {System.out.println("Even");System.out.println("Even");System.out.println(1001);System.out.println(1001);System.out.println(2024);System.out.println(2024);ConstDemo demo = new ConstDemo();PrintStream var10000 = System.out;Objects.requireNonNull(demo);var10000.println(255);var10000 = System.out;Objects.requireNonNull(demo);var10000.println(255);int number = true;System.out.println(9);System.out.println(9);System.out.println("--------------------------------");byte count;if (width > 100) {count = 1;} else {count = 2;}System.out.println(count);System.out.println(count);System.out.println(width);System.out.println(width);System.out.println(demo.height);System.out.println(demo.height);int weight = 99;System.out.println(weight);System.out.println(weight);}
}

如上代码,可以发现,只要是final修饰的变量在调用时直接被常量值替代了,有一个例外,就是在局部变量中声明的final int count;,它不是在声明时直接赋值的,而是经过一个if判断之后才赋值的,所以需要在运行时才能确定它的值是多少,所以在编译为字节码时调用该变量的地方没有被常量值替换,因为此时不知道它的值是多少。

另外也看到了一些有趣的地方,编译时编译器会有一些优化,比如int number = true;还能这样啊?没搞懂,它的final被去掉了,count中地final修饰符也被去掉了,而且类型变成了byte类型,编译器通过if中的判断得出值不是1就是2,用byte足已,所以改成了byte类型。

基于这个常量的特性,我们可以猜到,通过反射也是无法修改final类型的常量的,示例如下:

public class ConstDemo {public static final int age = 18;public static void main(String[] args) throws Exception {Field field = ConstDemo.class.getField("age");System.out.println("age = " + field.get(null));field.set(null, 30);System.out.println(age);}
}

运行结果如下:

age = 18
Exception in thread "main" java.lang.IllegalAccessException: Can not set static final int field ConstDemo.age to java.lang.Integerat java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:80)at java.base/jdk.internal.reflect.UnsafeQualifiedStaticIntegerFieldAccessorImpl.set(UnsafeQualifiedStaticIntegerFieldAccessorImpl.java:77)at java.base/java.lang.reflect.Field.set(Field.java:799)at ConstDemo.main(ConstDemo.java:9)

从这里也可以看出,为什么常量在编译为class字节码之后,调用它的地方已经被常量值所替换,为什么常量的声明语句还保留了,因为还是有可能会被用到的,比如我们通过反射读取该常量的值,这是需要在运行时才能完成的,无法在编译阶段就直接使用常量值替代的。

再来看一个Demo:

public class ConstDemo {public final int age = 18;public static final ConstDemo demo = new ConstDemo();public static void main(String[] args) throws Exception {System.out.println(demo);System.out.println(demo);System.out.println(demo.age);System.out.println(demo.age);}
}

编译为字节码后,再反编译结果如下:

public class ConstDemo {public final int age = 18;public static final ConstDemo demo = new ConstDemo();public ConstDemo() {}public static void main(String[] args) throws Exception {System.out.println(demo);System.out.println(demo);PrintStream var10000 = System.out;Objects.requireNonNull(demo);var10000.println(18);var10000 = System.out;Objects.requireNonNull(demo);var10000.println(18);}
}

可以看到声明为非原始类型的final常量在编译为字节码时无法使用常量值代替,因为它是一个对象,而对象的内存地址得在运行时才能确定,所以这种不应该叫常量的,所以,kotlin在这方面就做的比较好,表示一个变量不可改变用val,表示一个常量用const val,分得更加清楚,示例如下:

const val NAME = "Even"class ConstDemo {val width = 100var height = 200companion object {const val ID = 1001@JvmStaticfun main(args: Array<String>) {println(NAME)println(NAME)println(ID)println(ID)val demo = ConstDemo()println(demo.width)println(demo.height)}}}

可以看到,声明常量的地方只能是顶级属性或者companion object中,要查看反编译,如果直接在IntelliJ中找到class文件然后双击会发现反编译不了,我们可以这样查看:工具 > Kotlin > 显示Kotlin字节码 > 反编译,结果如下:

public final class ConstDemo {private final int width = 100;private int height = 200;public static final int ID = 1001;public final int getWidth() {return this.width;}public final int getHeight() {return this.height;}public final void setHeight(int var1) {this.height = var1;}public static final void main(@NotNull String[] args) {Intrinsics.checkNotNullParameter(args, "args");String var2 = "Even";System.out.println(var2);var2 = "Even";System.out.println(var2);short var4 = 1001;System.out.println(var4);var4 = 1001;System.out.println(var4);ConstDemo demo = new ConstDemo();int var3 = demo.getWidth();System.out.println(var3);var3 = demo.getHeight();System.out.println(var3);}
}public final class ConstDemoKt {@NotNullpublic static final String NAME = "Even";
}

在Kotlin中,常量只能是8大原始类型,不能是对象类型的,如下代码在编译器就报错了:
在这里插入图片描述
声明常量有什么好处?这里我想到之前写的一篇文章:https://blog.csdn.net/android_cai_niao/article/details/113571171

相关文章:

java常量和kotlin常量

在java中使用final声明常量在kotlin中使用const val声明常量 常量在编译为字节码后会直接把调用常量的地方直接替换为常量值&#xff0c;示例如下&#xff1a; public class ConstDemo {public static final String NAME "Even";private static final int ID 100…...

Python学习笔记--创建最简单的自定义异常类

在Python中&#xff0c;当创建一个函数时&#xff0c;它应该执行一些操作或返回一些值。如果函数为空&#xff0c;则没有实际的操作或返回值&#xff0c;这是不符合函数设计的初衷的。因此&#xff0c;在Python中&#xff0c;函数体不能为空&#xff0c;必须至少包含一个语句&a…...

2024年,AI 掀起数据与分析市场的新风暴

2024 年伊始&#xff0c;Kyligence 联合创始人兼 CEO 韩卿在其公司内部的飞书订阅号发表了多篇 Rethink Data & Analytics 的内部信&#xff0c;分享了对数据与分析行业的一些战略思考&#xff0c;尤其是 AI 带来的各种变化和革命&#xff0c;是如何深刻地影响这个行业乃至…...

小程序软件测试应该怎么做?有什么作用?

近年来&#xff0c;随着移动互联网的快速发展&#xff0c;小程序软件的使用越来越广泛。无论是企业推广还是个人创作&#xff0c;小程序软件都具备了很大的潜力和市场空间。然而&#xff0c;在发布之前&#xff0c;进行充分的测试是至关重要的&#xff0c;以确保用户体验的顺畅…...

springboot2.2.9整合kafka之KafkaListener实现原理

1、开启kafka的注解EnableKafka 通过开启kafka注解可以看到Import的类KafkaListenerConfigurationSelector加载一个配置类KafkaBootstrapConfiguration&#xff0c;而此类中有两个重要的类: KafkaListenerAnnotationBeanPostProcessor、KafkaListenerEndpointRegistry 2、Kaf…...

数据结构day7

1.思维导图 1.二叉树递归创建 2.二叉树先中后序遍历 3.二叉树计算节点 4.二叉树计算深度。 5.编程实现快速排序降序...

cleanmymacX有必要买吗

CleanMyMac X是一款被广泛推荐的Mac电脑清理软件。以下是关于是否购买CleanMyMac X的几个关键点&#xff1a; 软件功能&#xff1a;CleanMyMac X具备多项功能&#xff0c;包括但不限于系统垃圾清理、缓存清理、恶意软件移除、隐私保护等。这些功能有助于保持Mac电脑的清洁和性能…...

智慧文旅:打造无缝旅游体验的关键

随着科技的快速发展和消费者需求的不断升级&#xff0c;旅游业正面临着前所未有的变革压力。智慧文旅作为数字化转型的重要领域&#xff0c;旨在通过智能化、数据化手段为游客提供更加优质、便捷、个性化的服务&#xff0c;打造无缝的旅游体验。本文将深入探讨智慧文旅在打造无…...

C语言 | 求最大/小值小技巧:fmax、fmin函数

如果你只是因为不想用C语言手写max、min函数&#xff0c;就直接去用iostream中的max、min函数的话&#xff0c;这篇文章可能会有些许帮助。 &#x1f607; fmax、fmin函数用于确定两个指定值的较大/较小值。 头文件 math.h&#xff08;或者cmath&#xff09;。 定义 double …...

【深度学习每日小知识】Model Accuracy 模型准确率

Model Accuracy 模型准确率 模型准确性是衡量机器学习 (ML) 模型基于数据做出预测或决策的能力的指标。它是用于评估 ML 模型性能的常用指标&#xff0c;可用于比较不同模型的性能或评估特定模型对于给定任务的有效性。 有多种不同的方法来衡量模型的准确性&#xff0c;具体取…...

智能AI系统开发,专业软件硬件物联网开发公司,探索未来科技新纪元

在信息时代&#xff0c;人工智能&#xff08;AI&#xff09;、物联网等前沿技术日益受到人们的关注。智能AI系统、专业软件硬件物联网开发公司应运而生。今天&#xff0c;我们将向大家介绍一家位于XX城的专业公司&#xff0c;致力于智能AI系统开发和软件硬件物联网领域的创新研…...

第七篇:node中间件详解

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! ​ 目录 &#x1f4d8; 引言&#xff1a; &#…...

Jenkins自动化打包

Jenkins自动化打包 下载安装 我们直接从官网https://www.jenkins.io/download/ 下载所需的Jenkins文件 如上图所示, 选择Windows版本,下面就是一路安装即可,需要注意的是,选择作为系统服务选项, 不要自己设置账号密码登录. Web配置 安装完根据提示在浏览器打开 http://lo…...

【服务端性能测试】性能测试策略如何做

一、需求收集 先需要确认本次测试目的是什么&#xff0c;然后再看我们需要用什么参数来判断这个目的是否能够达成。 1.1 业务性能指标参考&#xff1a; TPS、QPS、RT、请求成功率&#xff08;一般请求成功率>99.99%&#xff09; 1.2 硬件性能指标参考&#xff1a; 即服…...

透明拼接屏造型:多样拼接与影响因素

透明拼接屏&#xff0c;以其独特的透明显示效果和灵活的拼接方式&#xff0c;在现代显示领域中独树一帜。其造型多样&#xff0c;包括横屏拼接、竖屏拼接、异形拼接以及定制拼接等多种方式&#xff0c;满足了不同场景和应用的需求。尼伽小编将详细介绍这些拼接方式&#xff0c;…...

c# 对路径的访问被拒绝

c#写入一个文件&#xff0c;报错&#xff1a; c# 对路径的访问被拒绝 解决方法&#xff1a; 检查文件路径和目录权限&#xff1a; 确保你的应用程序有权限写入指定的文件或目录。在某些情况下&#xff0c;你可能需要以管理员身份运行应用程序或更改文件/目录的权限。 确保目…...

【数据结构】单调队列

参考这篇文章 单调队列的作用是&#xff1a;给定一个长度为 n 的数组&#xff0c;维护长度为 m 的区间最大/小值 &#xff08;下面以维护区间最小值为例&#xff0c;最大值相反&#xff09; 简单来说就是维护一个 deque&#xff0c;deque 的队头是当前最小值的序号&#xff…...

《统计学习方法:李航》笔记 从原理到实现(基于python)-- 第5章 决策树(代码python实践)

文章目录 第5章 决策树—python 实践书上题目5.1利用ID3算法生成决策树&#xff0c;例5.3scikit-learn实例 《统计学习方法&#xff1a;李航》笔记 从原理到实现&#xff08;基于python&#xff09;-- 第5章 决策树 第5章 决策树—python 实践 import numpy as np import pand…...

电脑可以设置代理IP吗

首先需要回答的是&#xff0c;电脑可以设置代理IP&#xff0c;下面我们详细说说如何设置。 首先&#xff0c;我们使用工具来完成&#xff0c;使用工具的好处就是可以设置单独的软件使用代理&#xff0c;也可以设置全局&#xff0c;比较方便 我们解压这个文件出来&#xff0c;打…...

Zookeeper服务注册与发现实战

目录 设计思路 Zookeeper注册中心的优缺点 SpringCloudZookeeper实现微服务注册中心 第一步&#xff1a;在父pom文件中指定Spring Cloud版本 第二步&#xff1a;微服务pom文件中引入Spring Cloud Zookeeper注册中心依赖 第三步&#xff1a; 微服务配置文件application.y…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天&#xff0c;通信网络的角色正变得愈发关键。 2025年6月6日&#xff0c;为期三天的华南国际工业博览会在深圳国际会展中心&#xff08;宝安&#xff09;圆满落幕。作为国内工业通信领域的技术型企业&#xff0c;光路科技&#xff08;Fiberroad&…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用

前言&#xff1a;我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM&#xff08;Java Virtual Machine&#xff09;让"一次编写&#xff0c;到处运行"成为可能。这个软件层面的虚拟化让我着迷&#xff0c;但直到后来接触VMware和Doc…...

ubuntu22.04 安装docker 和docker-compose

首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

Linux安全加固:从攻防视角构建系统免疫

Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...