先看一段代码:

  1. package com.anjoyo.test; 
  2.  
  3. public class TestString { 
  4.         public static void main(String[] args) { 
  5.                 String s1="abc"
  6.                 String s2="abc"
  7.                 String s3=new String("abc"); 
  8.                 String s4=new String("abc"); 
  9.                 String s5="abcd"
  10.                 String s6=s1+"d"
  11.                 String s7="abc"+"d"
  12.                 System.out.println(s1==s2); //true 
  13.                 System.out.println(s1.equals(s2));//true 
  14.                 System.out.println(s3==s4);//false 
  15.                 System.out.println(s3.equals(s4));//true 
  16.                 System.out.println(s5==s6);//false 
  17.                 System.out.println(s5==s7);//true 
  18.     } 

首先应明确,String不是8中基本数据类型中的,它是引用数据类型。创建String对象有两种办法:

1. String s = "abc";这种赋值其实分为三步

   step1:在字符串池中找是否有值为"abc"的对象。这里有个常量池的概念,所谓常量池就是指在编译期间被确定,并被保存在已编译的.class文件中的一些数据,包括接口、类中的常量,也包括字符串常量,也就是我们说的字符串池。

   step2:若有,则把对该象的引用赋给s,所以这里的s2和s1指向了同一个对象。

   step3:若没有,就创建一个值为abc的对象并将该对象的引用存在池中,然后赋给s。

这里的s1和s2都是字符串常量,它们在编译期间就被确定,所以s1==s2为true,而s7为两个字符串常量的和,所以也是字符串常量,所以s5==s7结果也为true。
2. String s = new String("abc");这种赋值方式跟字符串池没有关系,每次都调用构造方法新建对象。所以s3,s4用==比较时为false,而字符串中equals比较的是字符串的内容是否相等,所以为s3.equals(s4)为true。
 
一般,基本数据类型比较用==,引用数据类型比较用equals。