Java核心之Java内存分配原理(二)

JAVA内存分配与管理是Java的核心技术之一,之前我们曾介绍过Java的内存管理与内存泄露以及Java垃圾回收方面的知识,今天我们再次深入Java核心,详细介绍一下Java在内存分配方面的知识。

创新互联建站专注为客户提供全方位的互联网综合服务,包含不限于网站设计制作、成都做网站、保靖网络推广、小程序制作、保靖网络营销、保靖企业策划、保靖品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;创新互联建站为所有大学生创业者提供保靖建站搭建服务,24小时服务热线:028-86922220,官方网址:www.cdcxhl.com

String常量池问题的几个例子

下面是几个常见例子的比较分析和理解:

 
 
  1. String a = "a1"; 
  2. String b = "a" + 1; 
  3. System.out.println((a == b)); //result = true 
  4. String a = "atrue"; 
  5. String b = "a" + "true"; 
  6. System.out.println((a == b)); //result = true 
  7. String a = "a3.4"; 
  8. String b = "a" + 3.4; 
  9. System.out.println((a == b)); //result = true 

分析:JVM对于字符串常量的"+"号连接,将程序编译期,JVM就将常量字符串的"+"连接优化为连接后的值,拿"a" + 1来说,经编译器优化后在class中就已经是a1。在编译期其字符串常量的值就确定下来,故上面程序最终的结果都为true。

 
 
  1. String a = "ab"; 
  2. String bb = "b"; 
  3. String b = "a" + bb; 
  4. System.out.println((a == b)); //result = false 

分析:JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的,即"a" + bb无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给b。所以上面程序的结果也就为false。

 
 
  1. String a = "ab"; 
  2. final String bb = "b"; 
  3. String b = "a" + bb; 
  4. System.out.println((a == b)); //result = true 

分析:和[3]中***不同的是bb字符串加了final修饰,对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量 池中或嵌入到它的字节码流中。所以此时的"a" + bb和"a" + "b"效果是一样的。故上面程序的结果为true。

 
 
  1. String a = "ab"; 
  2. final String bb = getBB(); 
  3. String b = "a" + bb; 
  4. System.out.println((a == b)); //result = false 
  5. private static String getBB() { 
  6. return "b"; 

分析:JVM对于字符串引用bb,它的值在编译期无法确定,只有在程序运行期调用方法后,将方法的返回值和"a"来动态连接并分配地址为b,故上面 程序的结果为false。

通过上面4个例子可以得出得知:

 
 
  1. String s = "a" + "b" + "c"; 

就等价于

 
 
  1. String s = "abc"; 
  2. String a = "a"; 
  3. String b = "b"; 
  4. String c = "c"; 
  5. String s = a + b + c; 

这个就不一样了,最终结果等于:

 
 
  1. StringBuffer temp = new StringBuffer(); 
  2. temp.append(a).append(b).append(c); 
  3. String s = temp.toString(); 

由上面的分析结果,可就不难推断出String 采用连接运算符(+)效率低下原因分析,形如这样的代码:

 
 
  1. public class Test { 
  2. public static void main(String args[]) { 
  3. String s = null
  4. for(int i = 0; i < 100; i++) { 
  5. s += "a"; 

每做一次 + 就产生个StringBuilder对象,然后append后就扔掉。下次循环再到达时重新产生个StringBuilder对象,然后 append 字符串,如此循环直至结束。如果我们直接采用 StringBuilder 对象进行 append 的话,我们可以节省 N - 1 次创建和销毁对象的时间。所以对于在循环中要进行字符串连接的应用,一般都是用StringBuffer或StringBulider对象来进行 append操作。

String对象的intern方法理解和分析:

 
 
  1. public class Test4 { 
  2. private static String a = "ab"; 
  3. public static void main(String[] args){ 
  4. String s1 = "a"; 
  5. String s2 = "b"; 
  6. String s = s1 + s2; 
  7. System.out.println(s == a);//false 
  8. System.out.println(s.intern() == a);//true 

这里用到JAVA里面是一个常量池的问题。对于s1+s2操作,其实是在堆里面重新创建了一个新的对象,s保存的是这个新对象在堆空间的的内容,所 以s与a的值是不相等的。而当调用s.intern()方法,却可以返回s在常量池中的地址值,因为a的值存储在常量池中,故s.intern和a的值相等。

总结

栈中用来存放一些原始数据类型的局部变量数据和对象的引用(String,数组.对象等等)但不存放对象内容堆中存放使用new关键字创建的对象.字符串是一个特殊包装类,其引用是存放在栈里的,而对象内容必须根据创建方式不同定(常量池和堆).有的是编译期就已经创建好,存放在字符串常 量池中,而有的是运行时才被创建.使用new关键字,存放在堆中。

网站题目:Java核心之Java内存分配原理(二)
网站地址:http://www.shufengxianlan.com/qtweb/news46/122746.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联