Java String 字符串创建理解 equels和"==" 差异

String是一个非可变类(immutable)。

什么是非可变类呢?简单说来,非可变类的实例是不能被修改的,每个实例中包含的信息都必须在该实例创建的时候就提供出来,并且在对象的整个生存周期内固定不变。

 

  好了,知道String是非可变类以后,我们可以进一步了解String的构造方式了。创建一个Stirng对象,主要就有以下两种方式:

  
  

String str1 = new String("abc");

  Stirng str2 = "abc";

  虽然两个语句都是返回一个String对象的引用,但是jvm对两者的处理方式是不一样的。

[b]对于第一种,jvm会马上在heap(堆)中创建一个String对象,然后将该对象的引用返回给用户。[/b]

对于第二种,jvm首先会在内部维护的strings pool(我称之为字符串对象池,以下我简称之为 对象池)中通过String的 equels 方法查找是对象池中是否存放有该String对象,如果有,则返回已有的String对象给用户,而不会在heap中重新创建一个新的String对象;如果对象池中没有该String对象,jvm则在heap中创建新的String对象,将其引用返回给用户,同时将该引用添加至strings pool中。注意:使用第一种方法创建对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法。

看下面的例子:
public class str {
public static void main(String[] args) {
//在堆上创建一个“abc”对象,但是jvm不会主动把该对象引用放到strings pool,
//而equels比较字符串呢,是要到strings pool 里面来做比较的!
String str1 = new String("abc");

//jvm 先在对象池中查找是否有“abc”对象,如果没有则在堆中创建一个“abc”对象,并把引用放到对象池中
String str2 = "abc";

//这个时候 堆中有两个"abc"对象
if (str1 == str2)
System.out.println("str1 == str2");
else
System.out.println("str1 != str2");


}
} 
 

[b]这里为什么不用equels而用==呢?[/b]
其实equels是用来比较两个字符串是否相同而已,无论字符串是否是同一个对象,都会返回true,只要是相同就OK了。而"=="则是既要看是否相同,还要看是否同一个对象才能返回true,否则返回false;这就是为什么我们有时候写程序用"=="不能判断字符串而用equels。当然对于理解String比较深的人而言就不存在这个问题了。老师教我们的比较字符串都用equels不要用"==".
我想"=="就相当于数学上比较两个三角形是否全等
equels则是比较两个三角形是否相似;

  [b]打印结果是 str1 != str2,因为它们是堆上两个不同的对象[/b]
 
 再看例子

  //此时,jvm发现strings pool中已有“abc”对象了,因为"abc"equels("abc")

  //因此直接返回str2指向的对象给str3,也就是说str2和str3是指向同一个对象的引用
public class str {
public static void main(String[] args) {
// 在堆上创建一个“abc”对象,但是jvm不会主动把该对象引用放到strings pool,
// 而equels比较字符串呢,是要到strings pool 里面来做比较的!
String str1 = new String("abc");

// jvm 先在对象池中查找是否有“abc”对象,如果没有则在堆中创建一个“abc”对象,并把引用放到对象池中
String str2 = "abc";

// 这个时候 堆中有两个"abc"对象
if (str1 == str2)
System.out.println("str1 == str2");
else
System.out.println("str1 != str2");

// jvm 又是先在对象池中查找是否有“abc”对象,一看,哦哦,有这个对象,于是就直接将“abc”的str2引用改成str3
String str3 = "abc";
if (str2 == str3)
System.out.println("str2 == str3");
else
System.out.println("str2 != str3");
//打印结果是 str2 == str3
}
}

  
  //打印结果为 str2 == str3

  再看下面的例子:

  public class str {
public static void main(String[] args) {
// 在堆上创建一个“abc”对象,但是jvm不会主动把该对象引用放到strings pool,
// 而equels比较字符串呢,是要到strings pool 里面来做比较的!
String str1 = new String("abc");

//这个方法就是将引用放到对象池中
str1 = str1.intern();

// jvm 先在对象池中查找是否有“abc”对象,如果没有则在堆中创建一个“abc”对象,并把引用放到对象池中
String str2 = "abc";

// 这个时候,因为上面str1调用了intern方法,对象池中有了str1对“abc”的引用 此时堆中有只有一个"abc"对象
if (str1 == str2)
System.out.println("str1 == str2");
else
System.out.println("str1 != str2");

// jvm 又是先在对象池中查找是否有“abc”对象,一看,哦哦,有这个对象,于是就直接将“abc”的str2引用改成str3
String str3 = "abc";
if (str2 == str3)
System.out.println("str2 == str3");
else
System.out.println("str2 != str3");
//打印结果是 str2 == str3
}
}
  

//打印结果是 str1 == str2

附件,本文中的测试程序
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值