Java编译时常量和运行时常量

编译期常量指的就是程序在编译时就能确定这个常量的具体值。

非编译期常量就是程序在运行时才能确定常量的值,因此也称为运行时常量。

在Java中,编译期常量指的是用final关键字修饰的基本类型或String类型并直接赋值(非复杂运算)的变量(无论是否用static修饰),是编译器的一种优化,体现在字节码文件中;运行是常量是由运行时解释器解释完成的

运行时常量很容易理解,接下来会简单的结合字节码文件来介绍编译时常量及使用风险。

  1. public class ConstantTest {
  2. public final int a = 1; //编译时常量
  3. public final int b = 1+2; //编译时常量 支持加减乘除等简单运算
  4. public final int c = b+3; //编译时常量
  5. public final static int d = 10; //编译时常量
  6. public final String str1 = "abc"; //编译时常量
  7. public final String str2 = "def" + "ghi"; //编译时常量 支持字符串的连接
  8. public final String str3 = str2 + "jkl"; //编译时常量
  9. public final static String str4 = "static str"; //编译时常量
  10. public final double e = Math.random(); //运行时常量
  11. public final ConstantTest test = new ConstantTest(); //运行时常量
  12. }

下面是编译后相应的字节码信息:

 注意!!!!!!

类B中所有引用类A中用static final修饰的静态编译时常量都会在编译时全部替换为相应的数值或字符串,所以当修改了类A中的静态编译时常量时,类A和类B都要重新编译,如果只重新编译类A,则类B还是会引用之前的常量。

以下是案例:

类ConstantTest:

  1. public class ConstantTest {
  2. public final int a = 1;
  3. public final int b = 1+2;
  4. public final int c = b+3;
  5. public final static int d = 10;
  6. public final String str1 = "abc";
  7. public final String str2 = "def" + "ghi";
  8. public final String str3 = str2 + "jkl";
  9. public final static String str4 = "static str";
  10. public final double e = Math.random();
  11. public final ConstantTest test = new ConstantTest();
  12. }

类Test引用ConstantTest中的静态编译时常量:

  1. public class Test{
  2. public int m = ConstantTest.d;
  3. public static int n = ConstantTest.d;
  4. public final int g = ConstantTest.d;
  5. public static final int j = ConstantTest.d;
  6. public static void main(String[] args) {
  7. int k = ConstantTest.d;
  8. System.out.println("m="+new Test().m);
  9. System.out.println("n="+n);
  10. System.out.println("g="+new Test().g);
  11. System.out.println("j="+j);
  12. System.out.println("k="+k);
  13. }
  14. }

  首先全部编译,运行Test类:

  修改ConstantTest中静态常量的值为20后只重新编译ConstantTest,运行结果:

  重新编译Test后,运行结果:

  最后总结一下:

  1. 编译期常量指的是用final关键字修饰的基本类型或String类型并直接赋值(非复杂运算)的变量(无论是否用static修饰);
  2. 运行时常量是程序在运行时才能确定值的一种常量;
  3. 所有引用其他类中静态编译时常量(一般就叫静态常量,用static final修饰)的类在字节码中全部替换为相应常量的值,所以引用静态常量并不会触发该类的的初始化。

Java编译时常量和运行时常量的更多相关文章

  1. Java编译时多态和运行时多态

    来源:https://blog.csdn.net/wendizhou/article/details/73733061 编译时多态:主要是方法的重载,通过参数列表的不同来区分不同的方法. 运行时多态: ...

  2. 正确理解java编译时,运行时以及构建时这三个概念

    Java中的许多对象(一般都是具有父子类关系的父类对象)在运行时都会出现两种类型:编译时类型和运行时类型,例如:Person person = new Student();这行代码将会生成一个pers ...

  3. [转] Java 的泛型擦除和运行时泛型信息获取

    原文链接 https://my.oschina.net/lifany/blog/875769 前言 现在很多程序员都会在简历中写上精通 Java.但究竟怎样才算是精通 Java 呢?我觉得不仅要熟练掌 ...

  4. 将子类对象引用赋值给超类对象 JAVA 编译时多态性

    将子类对象引用赋值给超类对象 JAVA 编译时多态性(转) (2012-05-10 11:24:05) 转载▼ 标签: 杂谈 分类: 也无晴_soft 1.通过将子类对象引用赋值给超类对象引用变量来实 ...

  5. in C#,编译型常量(const)和运行时常量(readonly)

    readonly 关键字与 const 关键字不同. const 字段只能在该字段的声明中初始化. readonly 字段可以在声明或构造函数中初始化. 因此,根据所使用的构造函数, readonly ...

  6. 关于JAVA编译时找不到自定义包的问题

    这两天照网上的教程,学习JSP/SERVLET/JAVABEAN,写了几个JAVA文件,目录放在TOMCAT的WEBAPPS下面,通过javac编译时,老提示找不到指定的包: 下图是我的目录路径: 通 ...

  7. java 编译时注解框架 lombok-ex

    lombok-ex lombok-ex 是一款类似于 lombok 的编译时注解框架. 编译时注,拥有运行时注解的便利性,和无任何损失的性能. 主要补充一些 lombok 没有实现,且自己会用到的常见 ...

  8. Java编译时根据调用该方法的类或对象所属的类决定

    class Base{     int x = 1;     static int y = 2; } class Subclass extends Base{     int x = 4;     i ...

  9. Java方法区和运行时常量池溢出问题分析

    运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名.访问修饰符.常量池.字段描述.方法描述等. String.intern()是一个native方法,它的作用是:如果字符串常量池 ...

随机推荐

  1. 补习系列(20)-大话 WebSocket 与 "尬聊"的实现

    目录 一.聊聊 WebSocket 二.Stomp 是个什么鬼 三.SpringBoot 整合 WebSocket A. 引入依赖 B. WebSocket 配置 C. 控制器 D. 前端实现 四.参 ...

  2. 【Elasticsearch 7 探索之路】(五)搜索相关 Search-API

    本节主要讲解 Elasticsearch 的 搜索相关功能 Search-API,讲解什么是 URL Search 和 Request Body Search 的语法,对常用的语法都会一一进行详细介绍 ...

  3. Use Swift Dynamic Framework (如何科学地引用第三方 Swift 库)

    转自:http://andelf.github.io/blog/2014/07/07/use-swift-dynamic-library/ CocoaPods 由于完全使用静态链接解决方法,过度依赖 ...

  4. RabbitMQ的三大交换器

    pom文件都是相同的 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

  5. MongoDB第一天(MongoDB的简介和安装)

    MongoDB 简介 什么是 MongoDB MongoDB 是一个基于分布式文件存储的数据库.由 C++语言编写.在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关 ...

  6. servlet登录练习,并且记录访问次数

    Userservlet登录数据处理,包括访问页面次数处理: package com.szxy.test; import java.io.IOException; import javax.servle ...

  7. JSP+Servlet 实现:理财产品信息管理系统

    一.接业务,作分析 1.大致业务要求 1.1 使用 JSP+Servlet 实现理财产品信息管理系统,MySQL5.5 作为后台数据库,实现查看理财 和增加理财功能 1.2 查询页面效果图 1.3 添 ...

  8. 模拟摄像头,AV视频信号线解码,PAL制 NTSC,输入解码显示,终于搞定,记录下!

    模拟摄像头,AV视频信号线解码,PAL制 NTSC,输入解码显示,终于搞定,记录下! 咱们常用的摄像头,监控等,大多数都是AV信号,国内制式都是PAL,采用同轴,传输,这样的好处在于,传输距离可以很长 ...

  9. Dubbo学习系列之七(分布式订单ID方案)

    既然选择,就注定风雨兼程! 开始吧! 准备:Idea201902/JDK11/ZK3.5.5/Gradle5.4.1/RabbitMQ3.7.13/Mysql8.0.11/Lombok0.26/Erl ...

  10. 小白学 Python 爬虫(22):解析库 Beautiful Soup(下)

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...