JavaSe: String的编译期优化
Java的编译期优化
因为工作的原因,经常会在没有源码的情况下,对一些产品的代码进行阅读。有时在解决Bug时,在运行环境下会直接去看class文件的字节码,来确定运行中版本是否正确的。
在看字节码时,发现了一个有意思的现象:即便你在代码中使用了定义的常量,反编译后的代码仍会是字符串的字面量。
这个其实就是Java编译器在编译时做了优化,下面就用一个例子来说明一下:
public class StringTest {
public static final String a1="a";
public static String a2="a";
public static void main(String[] args) {
String a = "a";
final String b = "b";
final String c = a + b;
String d = a + b;
String e = a + "b";
String f = "a" + b;
String g = "a" + "b";
String h = "ab";
String i = new String(h);
String j = a1+b;
String k = a2+b;
System.out.println(c == h); // false
System.out.println(d == h); // false
System.out.println(e == h); // false
System.out.println(f == h); // true
System.out.println(g == h); // true
System.out.println(i == h); // false
System.out.println(j == h); // true
System.out.println(k == h); // false
// 字面量,final 都会在编译期被优化,并且会被直接运算好
// 所以 f,g,j 在编译期就直接变为"ab"
// 因为a,a2是变量, 所以使用到a,a2的表达式,都是在运行时才去计算的
}
}
使用 javap命令查看字节码如下:
结合localvariabletable,分析main执行的过程如下:

从这里面,可以很明显的看到 运行时加载到f,g,h,j 时,直接就是字面量“ab”。
java中的==的作用是值的比较:
1)对于boolean,int,char,short,double,float,byte,long 这8种基本类型的比较,是比较值是否相等。
2)对于对象的比较,是比较地址的。
字符串字面量,和用final 修饰的 boolean,int,char,short,double,float,byte,long的变量一样,被统称为常量,它们是存在于常量池中的。
常量池中的内容只保留一份。上面例子中的f,g,j,h都是常量,它们的地址是同一个。所以比较的结果就是true。
而其它的,都是在运行时计算出来的,他们是在heap内存区域的(与常量池不在同一区域),所以他们的地址也就不一样了。所以比较的结果就是false了。
同理,对于其它的 boolean,int,char,short,double,float,byte,long常量 ,也会在编译期进行优化的。
JavaSe: String的编译期优化的更多相关文章
- java编译期优化
java语言的编译期其实是一段不确定的操作过程,因为它可以分为三类编译过程: 1.前端编译:把.java文件转变为.class文件 2.后端编译:把字节码转变为机器码 3.静态提前编译:直接把*.ja ...
- java编译期优化与执行期优化技术浅析
java语言的"编译期"是一段不确定的过程.由于它可能指的是前端编译器把java文件转变成class字节码文件的过程,也可能指的是虚拟机后端执行期间编译器(JIT)把字节码转变成机 ...
- 数值类型中JDk的编译期检查和编译期优化
byte b1 = 5;//编译期检查,判断是否在byte范围内 byte b2 = 5+4;//编译期优化,相当于b2=9 byte b3 = 127;//编译通过,在byte范围内 byte b4 ...
- 【深入理解JAVA虚拟机】第4部分.程序编译与代码优化.1.编译期优化。这章编译和实战部分没理解通,以后再看。
1.概述 1.1.编译器的分类 前端编译器:Sun的Javac. Eclipse JDT中的增量式编译器(ECJ)[1]. 把*.java文件转变成*.class文件 JIT编译器:HotSpot ...
- 深入了解JVM虚拟机8:Java的编译期优化与运行期优化
java编译期优化 java语言的编译期其实是一段不确定的操作过程,因为它可以分为三类编译过程:1.前端编译:把.java文件转变为.class文件2.后端编译:把字节码转变为机器码3.静态提前编译: ...
- 《深入理解Java虚拟机》-----第10章 程序编译与代码优化-早期(编译期)优化
概述 Java语言的“编译期”其实是一段“不确定”的操作过程,因为它可能是指一个前端编译器(其实叫“编译器的前端”更准确一些)把*.java文件转变成*.class文件的过程;也可能是指虚拟机的后端运 ...
- jvm虚拟机笔记<五> 编译期优化
JVM的编译器可以分为三个编译器: 1.前端编译器:把.java转变为.class的过程.如Sun的Javac.Eclipse JDT中的增量式编译器(ECJ). 2.JIT编译器:把字节码转变为机器 ...
- JVM笔记——编译期的优化
一.编译过程 解析和填充符号表的过程 插入注解处理器的注解处理过程 语义分析与字节码生成过程 二.解析和填充符号表 解析包含两个过程:词法分析和语法分析 (一)词法分析 将源代码的字符流转变成标记(T ...
- constexpr:编译期与运行期之间的神秘关键字
Scott Meyers在effective modern c++中提到“If there were an award for the most confusing new word in C++11 ...
随机推荐
- Linux系列教程(二十二)——Linux的bash变量
上篇博客我们介绍了bash的一些基本功能,这是我们平时操作最频繁的.本篇博客我们介绍bash的变量,为后面编写shell脚本做铺垫. 1.什么是变量 变量是计算机内存的单元,其中存放的值可以改变. 当 ...
- Android Weekly Notes Issue #283
November 12th, 2017 Android Weekly Issue #283 本期内容包括Gradle相关的几篇,如封装繁杂依赖的技巧,通过kotlin dsl让gradle支持kotl ...
- [转载] Linux的Top命令解析
转载自http://www.jb51.net/LINUXjishu/34604.html.http://blog.csdn.net/hello_yang213/article/details/7455 ...
- python基础(二)-------数据类型
python开发基础篇(二)数据类型 python数据类型有: 1.数字 1.只能存放一个值 2.一经定义,不可更改 3.直接访问 主要的分类为:整型,长整型,(python2有长整型的概念Pytho ...
- node笔记-node的好基友monggoDB
mongoDB--非关系型数据库的佼佼者 mongodb是一个基于分布式文件存储的数据库,由c++语言编写. 特点:高性能.易部署.易使用. 下载地址:http://www.mongodb.org/d ...
- Python字符编码详解(转)
http://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html 在没有reload(sys)之前调用sys.setdefaultencoding ...
- _2Python_注释命名等基本操作
注释:注解,解释 主要用于在代码中给代码标识出相关的文字提示(提高代码的可读性)或调试程序,方便别人阅读和自己日后修改. Python中注释分为两类.单行注释:单行注释以#号开头,在一行内,#号后面的 ...
- 单节点下使用docker部署consul
部署consul 目前Consul使用的版本是: v1.0.1 本教程适用于刚刚开始学习consul并简单使用consul的同学,可以在短时间内了解conusl,配合官方文档https://www.c ...
- 新一代 CI 持续集成工具 flow.ci 正式开源
很高兴地宣布 flow.ci 在 Apache-2.0 协议下正式开源了.flow.ci 是国内首套开源持续集成(CI) 解决方案,帮助企业团队实现开发流程(build-test-deploy)自动化 ...
- Android破解学习之路(三)——Android游戏 切水果破解
经过前两篇破解教程,想必大家也是明白了破解的简单流程了. 先对APP进行试用,了解APP运行的大概流程,之后从APP中找出关键字(一般的关键字差不多都是支付失败),之后使用Androidkiller进 ...