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声明常量 常量在编译为字节码后会直接把调用常量的地方直接替换为常量值,示例如下: public class ConstDemo {public static final String NAME "Even";private static final int ID 100…...
Python学习笔记--创建最简单的自定义异常类
在Python中,当创建一个函数时,它应该执行一些操作或返回一些值。如果函数为空,则没有实际的操作或返回值,这是不符合函数设计的初衷的。因此,在Python中,函数体不能为空,必须至少包含一个语句&a…...
2024年,AI 掀起数据与分析市场的新风暴
2024 年伊始,Kyligence 联合创始人兼 CEO 韩卿在其公司内部的飞书订阅号发表了多篇 Rethink Data & Analytics 的内部信,分享了对数据与分析行业的一些战略思考,尤其是 AI 带来的各种变化和革命,是如何深刻地影响这个行业乃至…...
小程序软件测试应该怎么做?有什么作用?
近年来,随着移动互联网的快速发展,小程序软件的使用越来越广泛。无论是企业推广还是个人创作,小程序软件都具备了很大的潜力和市场空间。然而,在发布之前,进行充分的测试是至关重要的,以确保用户体验的顺畅…...
springboot2.2.9整合kafka之KafkaListener实现原理
1、开启kafka的注解EnableKafka 通过开启kafka注解可以看到Import的类KafkaListenerConfigurationSelector加载一个配置类KafkaBootstrapConfiguration,而此类中有两个重要的类: KafkaListenerAnnotationBeanPostProcessor、KafkaListenerEndpointRegistry 2、Kaf…...
数据结构day7
1.思维导图 1.二叉树递归创建 2.二叉树先中后序遍历 3.二叉树计算节点 4.二叉树计算深度。 5.编程实现快速排序降序...
cleanmymacX有必要买吗
CleanMyMac X是一款被广泛推荐的Mac电脑清理软件。以下是关于是否购买CleanMyMac X的几个关键点: 软件功能:CleanMyMac X具备多项功能,包括但不限于系统垃圾清理、缓存清理、恶意软件移除、隐私保护等。这些功能有助于保持Mac电脑的清洁和性能…...
智慧文旅:打造无缝旅游体验的关键
随着科技的快速发展和消费者需求的不断升级,旅游业正面临着前所未有的变革压力。智慧文旅作为数字化转型的重要领域,旨在通过智能化、数据化手段为游客提供更加优质、便捷、个性化的服务,打造无缝的旅游体验。本文将深入探讨智慧文旅在打造无…...
C语言 | 求最大/小值小技巧:fmax、fmin函数
如果你只是因为不想用C语言手写max、min函数,就直接去用iostream中的max、min函数的话,这篇文章可能会有些许帮助。 😇 fmax、fmin函数用于确定两个指定值的较大/较小值。 头文件 math.h(或者cmath)。 定义 double …...
【深度学习每日小知识】Model Accuracy 模型准确率
Model Accuracy 模型准确率 模型准确性是衡量机器学习 (ML) 模型基于数据做出预测或决策的能力的指标。它是用于评估 ML 模型性能的常用指标,可用于比较不同模型的性能或评估特定模型对于给定任务的有效性。 有多种不同的方法来衡量模型的准确性,具体取…...
智能AI系统开发,专业软件硬件物联网开发公司,探索未来科技新纪元
在信息时代,人工智能(AI)、物联网等前沿技术日益受到人们的关注。智能AI系统、专业软件硬件物联网开发公司应运而生。今天,我们将向大家介绍一家位于XX城的专业公司,致力于智能AI系统开发和软件硬件物联网领域的创新研…...
第七篇:node中间件详解
🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 📝 个人网站 :《 江城开朗的豌豆🫛 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 📘 引言: &#…...
Jenkins自动化打包
Jenkins自动化打包 下载安装 我们直接从官网https://www.jenkins.io/download/ 下载所需的Jenkins文件 如上图所示, 选择Windows版本,下面就是一路安装即可,需要注意的是,选择作为系统服务选项, 不要自己设置账号密码登录. Web配置 安装完根据提示在浏览器打开 http://lo…...
【服务端性能测试】性能测试策略如何做
一、需求收集 先需要确认本次测试目的是什么,然后再看我们需要用什么参数来判断这个目的是否能够达成。 1.1 业务性能指标参考: TPS、QPS、RT、请求成功率(一般请求成功率>99.99%) 1.2 硬件性能指标参考: 即服…...
透明拼接屏造型:多样拼接与影响因素
透明拼接屏,以其独特的透明显示效果和灵活的拼接方式,在现代显示领域中独树一帜。其造型多样,包括横屏拼接、竖屏拼接、异形拼接以及定制拼接等多种方式,满足了不同场景和应用的需求。尼伽小编将详细介绍这些拼接方式,…...
c# 对路径的访问被拒绝
c#写入一个文件,报错: c# 对路径的访问被拒绝 解决方法: 检查文件路径和目录权限: 确保你的应用程序有权限写入指定的文件或目录。在某些情况下,你可能需要以管理员身份运行应用程序或更改文件/目录的权限。 确保目…...
【数据结构】单调队列
参考这篇文章 单调队列的作用是:给定一个长度为 n 的数组,维护长度为 m 的区间最大/小值 (下面以维护区间最小值为例,最大值相反) 简单来说就是维护一个 deque,deque 的队头是当前最小值的序号ÿ…...
《统计学习方法:李航》笔记 从原理到实现(基于python)-- 第5章 决策树(代码python实践)
文章目录 第5章 决策树—python 实践书上题目5.1利用ID3算法生成决策树,例5.3scikit-learn实例 《统计学习方法:李航》笔记 从原理到实现(基于python)-- 第5章 决策树 第5章 决策树—python 实践 import numpy as np import pand…...
电脑可以设置代理IP吗
首先需要回答的是,电脑可以设置代理IP,下面我们详细说说如何设置。 首先,我们使用工具来完成,使用工具的好处就是可以设置单独的软件使用代理,也可以设置全局,比较方便 我们解压这个文件出来,打…...
Zookeeper服务注册与发现实战
目录 设计思路 Zookeeper注册中心的优缺点 SpringCloudZookeeper实现微服务注册中心 第一步:在父pom文件中指定Spring Cloud版本 第二步:微服务pom文件中引入Spring Cloud Zookeeper注册中心依赖 第三步: 微服务配置文件application.y…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...
