java运行时链接问题

serapme 2015-08-05 02:17:44
public static void main(String[] args) {
// TODO Auto-generated method stub
String a = "hello2";
final String b = "hello";
String d = "hello";
String c = b+2;
String e = d+2;
System.out.println(a == c);
System.out.println(a == e);
}
为什么会返回true 和 false呢 ,
帖子说final修饰的b可以预先优化 类似宏,而c要运行时链接,不明白原理,对运行时链接不太理解,请赐教
...全文
156 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
serapme 2015-08-07
  • 打赏
  • 举报
回复
引用 3 楼 owen1759 的回复:
我感觉可能是优化策略的问题,首先a是位于常量池里的大家没有异议吧? 运行结果上看c跟a指向了同一个地址,说明在编译时c被优化了。 再看c的初始化语句c=b+2,b是个常量(带final的),2也是常量,所以这样的优化是安全的。 那么为什么e没有优化呢?看e的初始化语句,e=d+2,d是个变量,虽然它初始化的时候是指向常量池的,但是它自身是一个变量,什么意思呢?是说它指向的地址是可以被改变的。那么就无法保证在对e进行初始化的时候d还是指向"hello"所以不能对e进行优化。 简单的说,就是只有常量参与的运算可以优化,涉及到变量的运算就不能优化。
c被优化了 为什么 a===c 就是true 而 a==e 为false,不太明白这里面的原因是什么? 是因为a 和e指向的地址不一样么?
owen1759 2015-08-07
  • 打赏
  • 举报
回复 2
没错,首先一个百分之百毫无异议的就是a所指向的字符串是在常量池里面的,这不是优化的结果,而是事实。 那么现在的问题就是c和e是否是指向常量池的。如果不经过任何优化,c和e都不会是指向常量池的,也就是说应该都为false,因为字符串相加是通过新建一个字符串对象实现的,所以,只要是字符串相加的结果,必然是新建的对象,不可能指向常量池。 然而编译器会对一些“确定的”情况进行优化,那么什么是确定的情况呢? String c = b +2 编译时会对这个算式进行检查,计算的第一个参数是b,而b是常量(带final的都是常量),也就意味着在程序的任何地方,b都必然等于其初始值"hello",所以编译器可以把这个语句安全的替换成String c = "hello" + 2; 然后再检查,发现"hello" + 2完全可以提前计算出来,于是就替换成String c = "hello2"; 所以你的程序经过优化器就被自动修改成了

public static void main(String[] args) {
String a = "hello2";
final String b = "hello";
String d = "hello";
String c = "hello2";
String e = d + String.valueOf(2);
System.out.println(a == c);
System.out.println(a == e);
}
这样的程序编译出来会是什么样子? 常量池:"hello2" "hello" 2 a指向常量"hello2" b指向常量"hello"(不可改变) d指向常量"hello" c指向常量"hello2" 将数字2转换成字符串"2" 新建字符串对象,其值为变量d与字符串"2"的连接 e指向新字符串 检查a与c指向同一地址,返回true 检查a与e指向不同地址,返回false 请注意,字符串是对象,等于号是用来判断对象地址是否相同的,检查字符串内容是否相同用equal 好比你的家门钥匙配了两把,你跟你媳妇一人一把,等于号是问你,你手上这把钥匙和你媳妇的是同一把钥匙(同一个对象)么?
dlhansy 2015-08-06
  • 打赏
  • 举报
回复
引用 3 楼 owen1759 的回复:
我感觉可能是优化策略的问题,首先a是位于常量池里的大家没有异议吧? 运行结果上看c跟a指向了同一个地址,说明在编译时c被优化了。 再看c的初始化语句c=b+2,b是个常量(带final的),2也是常量,所以这样的优化是安全的。 那么为什么e没有优化呢?看e的初始化语句,e=d+2,d是个变量,虽然它初始化的时候是指向常量池的,但是它自身是一个变量,什么意思呢?是说它指向的地址是可以被改变的。那么就无法保证在对e进行初始化的时候d还是指向"hello"所以不能对e进行优化。 简单的说,就是只有常量参与的运算可以优化,涉及到变量的运算就不能优化。
owen1759 2015-08-05
  • 打赏
  • 举报
回复
我感觉可能是优化策略的问题,首先a是位于常量池里的大家没有异议吧? 运行结果上看c跟a指向了同一个地址,说明在编译时c被优化了。 再看c的初始化语句c=b+2,b是个常量(带final的),2也是常量,所以这样的优化是安全的。 那么为什么e没有优化呢?看e的初始化语句,e=d+2,d是个变量,虽然它初始化的时候是指向常量池的,但是它自身是一个变量,什么意思呢?是说它指向的地址是可以被改变的。那么就无法保证在对e进行初始化的时候d还是指向"hello"所以不能对e进行优化。 简单的说,就是只有常量参与的运算可以优化,涉及到变量的运算就不能优化。
serapme 2015-08-05
  • 打赏
  • 举报
回复
引用 1 楼 scmod 的回复:
我也不是很清楚,大概意思是final的在编译保存的时候就会把变量替换成字符串来存, 不是final的在运行时候根据变量的引用来调用, 比如c在编译的时候其实就已经是"hello" + 2然后保存的时候就已经是hello2了 而e的话只是保存了d的引用+2在运行时根据d的引用地址去找那个具体是啥然后拿来拼接 我的理解貌似是这样的不一定对,这个东西绕啊绕啊绕啊.....然后就晕了
嗯 我也是理解的比较模糊,总感觉差点意思
scmod 2015-08-05
  • 打赏
  • 举报
回复
我也不是很清楚,大概意思是final的在编译保存的时候就会把变量替换成字符串来存, 不是final的在运行时候根据变量的引用来调用, 比如c在编译的时候其实就已经是"hello" + 2然后保存的时候就已经是hello2了 而e的话只是保存了d的引用+2在运行时根据d的引用地址去找那个具体是啥然后拿来拼接 我的理解貌似是这样的不一定对,这个东西绕啊绕啊绕啊.....然后就晕了

67,550

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧