First来说一个很重要的概念,就是
常量池:
所谓常量池:顾名思义就是用来存放一些常量的,该常量是在编译期被确定,并被保存在已编译的.class文件中,其中包括了关于类,方法,接口等其中包含的数值常量,字符常量和字符常量。
同时在常量池中,有个专门用来存储字符串常量的,称之为字符串常量池,当我们需要使用字符串时,首先会在该字符串常量中查找是否存在该字符串,若可以直接进行使用,若不存在,则会新建一个对应的字符串,并保存在该字符串常量池中。
另外一点,在编译期间创建的常量和运行期间创建的常量保存的地址是不一样的:
(对象的引用都是存放在栈中)
编译期间创建的常量保存在常量池中,
运行期间通过new创建时,会直接创建一个新字符串并会存储在堆中,
所以我们可以发现,在堆中,可以有很多重复相同的字符串,而在常量池中,不会出现重复的值。
理解这一点之后,我们接下来再来看看这两个的具体区别:
首先String str="";
例如:
String str=“abcd”;
这个表达式,可能会创建一个对象,可能不会创建一个对象,
常量池中没有“abcd”,这个字符串,就需要创建
常量池中由“abcd"这个字符串,就会直接拿来使用
String str=new String(“abcd”);
这个表达式,可能会创建一个对象,也可能会创建两个对象;
首先该new会直接创建一个字符串存放在堆中;
其次,同样的
常量池中没有“abcd”,这个字符串,就需要创建
常量池中由“abcd"这个字符串,就会直接拿来使用
如下例子:
String str1=new "abcd";
String str2=new "abcd";
System.out.println("str1==str2")//False,比较的是内存地址
System.out.println("str1.equals(str2)”);//true 比较的是内容
==比较类对象时,比较的是两个地址是否相同,所指向的对象指的是堆中的对象
==比较的是基本类型时,比较的是其内容也就是其值是否相等
equals()方法未被重写时(Object时),比较的是内存地址
equals()方法被String,Integer,Date等类重写时,其比较的是两个内容是否相同
String str1= "abcd";
String str2="abcd";
System.out.println("str1==str2")//true,所指向的是常量池中的对象,
System.out.println("str1.equals(str2)”);//true