Java编译器对于String常量表达式的优化

首先把问题摆出来,先看这个代码

String a = "ab";
String b = "a" + "b";
System.out.println((a == b));

打印结果会是什么?类似这样的问题,有人考过我,我也拿来考过别人(蛮好玩的,大家也可以拿来问人玩),一般答案会是以下几种:

1.true

"a" + "b" 的结果就是"ab",这样a,b都是"ab"了,内容一样所以"相等",结果true

一般java新人如是答。

2.false

"a" + "a"会生成新的对象"aa",但是这个对象和String a = "ab";不同,(a == b)是比较对象引用,因此不相等,结果false

对java的String有一定了解的通常这样回答。

3.true

String a = "ab";创建了新的对象"ab"; 再执行String b = "a" + "b";结果b="ab",这里没有创建新的对象,而是从JVM字符串常量池中获取之前已经存在的"ab"对象。因此a,b具有对同一个string对象的引用,两个引用相等,结果true.

能回答出这个答案的,基本已经是高手了,对java中的string机制比较了解。

很遗憾,这个答案,是不够准确的。或者说,根本没有运行时计算b = "a" + "b";这个操作.实际上运行时只有String b = "ab";

3的观点适合解释以下情况:

String a = "ab";
String b = "ab";
System.out.println((a == b));

如果String b = "a" + "b";是在运行期执行,则3的观点是无法解释的。运行期的两个string相加,会产生新的对象的。(本文后面对此有解释)

4.true

下面是我的回答:编译优化+ 3的处理方式 = 最后的true

String b = "a" + "b";编译器将这个"a" + "b"作为常量表达式,在编译时进行优化,直接取结果"ab",这样这个问题退化

String a = "ab";
String b = "ab";
System.out.println((a == b));

然后根据3的解释,得到结果true

这里有一个疑问就是String不是基本类型,像

int secondsOfDay = 24 * 60 * 60;

时间: 2024-12-24 21:57:31

Java编译器对于String常量表达式的优化的相关文章

Java中的String与常量池

string是java中的字符串.String类是不可变的,对String类的任何改变,都是返回一个新的String类对象.下面介绍java中的String与常量池. 1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. new String()和new String("")都是申明一个新的空字符串,是空串不是null: 3. String st

Java开发中程序和代码性能优化

现在计算机的处理性能越来越好,加上JDK升级对一些代码的优化,在代码层针对一些细节进行调整可能看不到性能的明显提升,在开发中注意这些,更多的是可以保持一种性能优先的意识. 一 条件控制语句中的优化 1.在循环中应该避免使用复杂的表达式. 在循环中,循环条件会被反复计算,应该避免把一些计算放在循环进行的部分中,程序将会运行的更快.比如: for(int i=0;i<list.size();i++) 可以改为 //我的电脑上,测试数量级在10^7,速度提升一倍. for(int i=0,len=li

编码准则与Java编译器

我们在写代码时,常常会提到两条原则: 1.方法要尽量短,大方法要分解成小方法: 2.不要重复发明轮子. 我们在强调这两个原则的时候,往往只关注的是代码简洁.易维护等方便我们人的因素,其实这样做还可以大大方便java编译器优化代码. Java编译器优化简介 Java应用程序的编译过程与静态编译语言(例如C或C++)不同.静态编译器直接把源代码转换成可以直接在目标平台上执行的机器代码,不同的硬件平台要求不同的编译器.Java编译器把Java源代码转换成可移植的JVM字节码.与静态编译器不同,java

Java中的String不再纠结

先分享一下java中string的一些小专题吧,这部分比比较基础,但是也非常的有用.我发现很多面试官像中了邪一样就爱问这个..string的种种,纠结,希望这篇文章让大家不再纠结.. string是我们经常用到的一个类型,其实有时候觉得写程序就是在反复的操作字符串,这是C的特点,在java中,jdk很好的封装了关于字符串的操作.今天主要讲的是三个类String .StringBuffer . StringBuilder .这三个类基本上满足了我们在不同情景下使用字符串的需求. 先说,第一个Str

Java 中的字符串常量池详解_java

Java中的字符串常量池 Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new String("droid");,这两种方式我们在代码编写时都经常使用,尤其是字面量的方式.然而这两种实现其实存在着一些性能和内存占用的差别.这一切都是源于JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池.

Java SE 6.0调用Java编译器的两种新方法

在很多Java应用中需要在程序中调用Java编译器来编译和运行.但在早期的版本中(Java SE5及以前版本)中只能通过tools.jar中的com.sun.tools.javac包来调用Java编译器,但由于tools.jar不是标准的Java库,在使用时必须要设置这个jar的路径.而在Java SE6中为我们提供了标准的包来操作Java编译器,这就是javax.tools包.使用这个包,我们可以不用将jar文件路径添加到classpath中了. 一.使用JavaCompiler接口来编译Ja

JVM深入学习笔记一:Java 编译器初探

闲来无事想大概看下Java编译器的执行过程 一. 编译一个文件 首先去搞到源代码.从JDK6开始Java代码开源,放到OPENJDK组织中去,所以从这个网站进行下载: http://hg.openjdk.java.net/jdk6/jdk6/langtools/  下载之后是一个zip包,解压,可以直接导入到eclipse中进行使用,导入之后可能会报错,需要设置一下. 好,下面写一个用作测试的类: import java.util.Arrays; import java.util.List; i

IDEA中调试Java编译器小结

之前有介绍过在NetBeans里面调式HotSpot,今天记录下怎么在IDEA里面调试Java编译器,也就是javac. 首先我们要先拿到javac的代码,它是在hotspot的子工程langtools里面,clone下来先, hg clone http://hg.openjdk.java.net/jdk7u/jdk7u/langtools 然后找到javac的代码入口,com.sun.tools.javac.main.Main. 为了偷懒我直接在这个类里面加了main方法, public st

java编译器顺序-java读取代码顺序是从左往右还是从右往左

问题描述 java读取代码顺序是从左往右还是从右往左 java编译器读取每行代码顺序是从左往右还是从右往左 例如 int a=1; int b=2; int c=3; int d=a+b*c int d=a+b*c是从左往右读取还是按优先级读取 编译器读取每行代码都是从左往右读取吗 解决方案 也许你觉得从左到右是很天经地义的事情. 偏偏阿拉伯文就是从右到左的. 我们知道,windows.office这些软件都有阿拉伯语言的版本,也能正确处理这些语言. 那么微软是否需要为这些国家或者地区的人重新设