Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4584698
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: Java

2014-01-13 03:41:39

文章来源:http://blog.163.com/woshihezhonghua@126/blog/static/1271436362012101214031911

首先明确一点,String是一个类。

 a) String类的对象的两种赋值方式

a) 1 类似普通对象,通过new创建字符串对象。String str = new String("Hello"); 内存图如下图所示,系统会先创建一个匿名对象"Hello"存入堆内存(我们暂且叫它A),然后new关键字会在堆内存中又开辟一块新的空间,然后把"Hello"存进去,并且把地址返回给栈内存中的str, 此时A对象成为了一个垃圾对象,因为它没有被任何栈中的变量指向,会被GC自动回收。

java String 两种不同的赋值 比较 - hzh - The Legend of 1900
 


a)2 直接赋值。如String str = "Hello";  首先会去缓冲池中找有没有一个"Hello"对象,如果没有,则新建一个,并且入池,所以此种赋值有一个好处,下次如果还有String对象也用直接赋值方式定义为“Hello”, 则不需要开辟新的堆空间,而仍然指向这个池中的"Hello"

java String 两种不同的赋值 比较 - hzh - The Legend of 1900

以下代码可以测试这一结论 ,最后输出结果为 true, 我们用的是== 测试,输出true,说明两者的地址是一样的
java String 两种不同的赋值 比较 - hzh - The Legend of 1900

a)3  手动入池
即使使用new关键字,第一种方式赋值,也可以使用一个java中的手动入池指令,让所创建的对象入池,以后依然可以背重复使用,利用下面两段代码可以测试, 如下图,结果显然是false,因为二者的地址不同。  

java String 两种不同的赋值 比较 - hzh - The Legend of 1900

 
 
下面程序中,我们使用了intern()方法,手动入池,所以结果是true.
public class TestString
{
 public static void main(String args[]){
  String str1 = new String("Hello").intern();
  String str2 = "Hello";
  System.out.println( str1==str2 );
 }
}
 
下面程序中,str2没有使用直接赋值,所以结果又变为false
public class TestString
{
 public static void main(String args[]){
  String str1 = new String("Hello").intern();
  String str2 = new String("Hello");
  System.out.println( str1==str2 );
 }
}
综上所述,开发中,使用直接赋值的方式,显然效率更高。
 
 
b) 为什么String类的对象可以直接赋值  

打开了String.class,有这么一段介绍:

[java] view plaincopy
  1. /** 
  2. * The String class represents character strings. All 
  3.  * string literals in Java programs, such as "abc", are 
  4.  * implemented as instances of this class. 
  5.  * 

     

  6.  * Strings are constant; their values cannot be changed after they 
  7.  * are created. String buffers support mutable strings. 
  8.  * Because String objects are immutable they can be shared. For example: 
  9.  * 

     
    			

  10.  *     String str = "abc"; 
  11.  * 

     

  12.  * is equivalent to: 
  13.  * 

     
    			

  14.  *     char data[] = {'a', 'b', 'c'}; 
  15.  *     String str = new String(data); 
  16.  * 

     

  17.  * Here are some more examples of how strings can be used: 
  18.  * 

     
    			

  19.  *     System.out.println("abc"); 
  20.  *     String cde = "cde"; 
  21.  *     System.out.println("abc" + cde); 
  22.  *     String c = "abc".substring(2,3); 
  23.  *     String d = cde.substring(1, 2); 
  24.  *  
  25.  * 

     

  26.  */  

通过上面的介绍,我们可以清楚,直接赋值的话,是通过编译器在起作用,当你对"abc"没有通过new创建时,他会自动默认给你调用构造函数new String(char value[]). 不显式调用String的构造函数(通过new叫显式调用),其实JDK编译器会自动给你加上。


JDK5+junit4.5写的例子,完全通过测试

import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;

import org.junit.Test;

/**
 * 
@author Heis
 *
 
*/
public class StringTest{

    @Test
    public void testTheSameReference1(){
        String str1="abc";
        String str2="abc";
        String str3="ab"+"c";
        String str4=new String(str2);
        
        //str1和str2引用自常量池里的同一个string对象
        assertSame(str1,str2);
        //str3通过编译优化,与str1引用自同一个对象
        assertSame(str1,str3);
        //str4因为是在堆中重新分配的另一个对象,所以它的引用与str1不同
        assertNotSame(str1,str4);
    }
    
}


阅读(820) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~