字符串的比较顺序
-
“==”用来比较两个变量的值是否相当,也就是运用该运算符比较变量,比较的是该变量对应内存中存储的数值是否相等(而变量是栈上的概念,所以可以理解成等号比较的是栈上的数据);
-
equals是object类提供的方法,它的实现也是==,而有的类将他复写了,所以才会有equals用于比较对象的内容;
-
创建字符串最平常的方式:
String str1 = "abcd";
String str2 = new String("abcd");
区别是有的:
第一种方式引用的是常量池的对象;第二种方式会先在常量池中先查找能不能找到"abcd"或"abcd"的引用,如果没有,那么就会在常量池创建字符"abcd",然后在堆上创建对象,对象中存储常量池字符的地址,同时在栈上创建str2,str2存储堆上对象的地址(创建了两个对象);如果找到了在堆上放的就是常量池的引用(创建了一个对象);
- 变形:
String str1 = "ab"+"cd";
String str2 = new String("ab")+new String("cd");
- 第一句在编译时已经将"ab"+"cd"换成"abcd"所以和String str1 = “abcd”;是一模一样的;
- 而第二句: 会在常量池中创建ab、cd并在堆上存储ab和cd在常量池的引用, 在栈上创建引用变量str2 ,而str2 引用的对象实体是"abcd",因此会在堆上创建"abcd",同时把"abcd"的地址复制给str2 ;
注意此时并没有把"abcd"放在字符串常量池中;
String str1 =new String("ab");
String str2 = new String("str1");
总结
无论如何只要是new 出来的string那么就会在堆上开辟空间,那么他在栈上的引用,引用的就是不同存储地址,所以当用s1==s2时都是false;
string比较
String s1 = "AB";
System.out.println(s1=="AB");//true
String s1 = new String("AB");
System.out.println(s1=="AB");//false
当我还在思考这个字面值常量“AB”,程序有没有为他开辟一个空间时(或者开辟的空间在哪里?)通过上面的代码已经验证了这个空间是存在的,它就是常量池;忽然间往事历历在目,所有的字面值常量都是存储在常量池中的;那么常量池中存储的都有什么?一种是字面值常量,一种的符号引用;
- 字面值常量:
- 文本字符串
- 被声明为final的值
- 基本数据类型值
- 符号引用
- 类的结构和完整限定名
- 字段名称和描述符;
- 方法名称和描s述符;
那么再看这段代码:
String s1=new String("A")+new String("B");
System.out.println(s1=="AB");
此时的"AB"已经有自己的常量池空间了(可以看作一个匿名对象),那么s1=="AB"时堆上的“AB”和常量是的“AB”就很显然不一样了结果为false;
String s1=new String("A")+new String("B");
System.out.println(s1==s1.intern());
System.out.println(s1=="AB");
此时话音戛然而止,意犹未尽着,更多精彩请看我的另一篇文章让人望而却步的String及intern()方法