怎么就不能比?你上面就等于 String a = "a"; String b = "a"; System.out.println(a == b); 他们比较的还是内存,只是a和b指向的是同一个内存,这里有个内存池的概念,在第一次String a = "a";的时候在内存池会分配一个a;第二次String b = "a";会先在内存池里找一个有没有"a"的,如果有a,b都去指向“a”
你说的是不对的。你可以自己对照内存想想。原生类型和引用类型你不能一概而论。String a ="1"; String b = "1";引用a,引用b.他们在栈中的地址是不一样的。但是他们地址中的内容是一样的,也就是他们指向的是同一对象。所以对于引用类型做==的时候,比较的是他们所指向的对象在内存中的地址是不是一样的。换句话说,指向的是不是同一个对象。对于原生类型。int a = 1; int b = 1;a和b在JVM栈中的地址是不一样的。而地址中的值是一样的都是1.所以a == b为真。显而易见,比较的值。而非你所说的地址。如果非要下个总结的话。因为不一定都在栈中,所以话不太好说。就用C来描述吧。pa = &a ;pb = &b;比较的是 *pa和*pb对于引用来说,*pa.就是他所指向对象的地址。 对于原生类型来说,*pa就是他的值。
String a = "a";
String b = "a";
System.out.println(a == b);
他们比较的还是内存,只是a和b指向的是同一个内存,这里有个内存池的概念,在第一次String a = "a";的时候在内存池会分配一个a;第二次String b = "a";会先在内存池里找一个有没有"a"的,如果有a,b都去指向“a”
String比较应该用equals()
看还是有很多人认识上有误区,所以再次简单的说明一下
==和equals比较的都是的两个内存空间的信息
==比较的是直接内存空间的信息(即变量本身的内存信息),equals比较的间接内存空间的信息(即对象本身的内存信息)首先要清楚“内存空间”,一个变量,本身有自己的内存空间,==就是比较两个变量本身的内存空间的信息,所以是“直接内存空间”,也就是变量本身的内存空间
比如
int a = 1; int b = 1; a==b,比较的是变量a内存的和变量b内存的信息
即a变量的内存信息的是 00000000 00000000 00000000 00000001 (二进制4个byte)
b变量的内存信息是是 00000000 00000000 00000000 00000001 (二进制4个byte)
因为a和b的内存信息一样,所以==是trueequals比较的是变量所引用的对象的内存空间的信息,即不是直接比较两个变量的内存空间的信息,而是比较两个变量所引用的对象的内存空间的信息,所以是“间接内存空间”,也就是对象本身的内存空间而不是变量自身的内存空间
比如
String a = "a"; String b = new String("a");
==比较的是变量a的内存和变量b的内存信息,变量a和b的内存空间里存放的是对象的地址
即a变量的内存是 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx (二进制4个byte "a"对象的地址)
b变量的内村信息是 yyyyyyyy yyyyyyyy yyyyyyyy yyyyyyyy (二进制4个byte,new String("a")对象的地址)
很显然,在这个例子里a的内存信息和b的内存信息不一样,也就是a和b引用的对象不一样,所以a==b是false
而eqauls比较的是对象的内存空间信息,
"a"对象的内存地址是 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx (也就是a变量的内存信息)
该内存地址保存的是00000000 00000061 ('a'字符的ascii码)
同样的new String("a")对象的内存地址是 yyyyyyyy yyyyyyyy yyyyyyyy yyyyyyyy (也就是b变量的内存信息)
该内村地址保存的是 00000000 00000061 ('a'字符的ascii码)
equals比较的是"a"对象和new String("a")对象的内存信息,所以a.equals(b)是true,因为对象的内存信息都是字符'a'的ascii码
可见,a和b两个变量所引用的对象虽然不同,既对象的地址不同,但是对象的内存信息相同,所以a==b是false(两个变量的内存信息不同),a.equals(b)是true(两个对象的内存信息相同)所以,==比较的是变量的内存信息(直接内存比较),eqauls比较的对象的内存信息(间接内存比较)
因为引用类型的变量的内存信息是对象的地址,所以简单的说==是比较地址,equals是比较内容
但是要清楚,==比较的变量本身的内存信息,equals比较的变量所引用的对象的内存信息
在这点上,学过C/C++的人(了解指针概念的人)都会比较好容易理解
小弟冒昧问下,我记得我当初学的时候记得时,看源码equals等同于==,之所以String特别,是因为String重写了equals方法,所以会和==不同,小弟才疏学浅,也不知对不对,有点疑惑了
我是这个意思啊,只是看八楼说的,只是适用于String,如果String没有重写equals方法,就和==一样了吧
只是因为很多人都说==是比较“地址”,却不知道这个所谓的比较“地址”是什么意思
所以想说明一下,==其实是比较两个变量的内存信息,equals是比较对象的内存信息(因为equals可以重写,所以要比较对象的什么信息可以由用户重写equals方法决定,不管怎么重写,目的都是为了希望对象的某些内存信息一样我们就认为是相同的)
打个比方,1.一对双胞胎如果用==号则是说他们2个是不是一个人,很明显2个人不可能是一个人。
2.equals方法则是说,他们长的是不是一样,这个就看观看者怎么看了,每个人可以有自己的方法,观点(相当于重写equals方法)在这个层面上,我们只是说尽量保持equals的2个对象里面的内容保持一致。
我当时也是这个师兄给我讲懂的哦。
equals比较的是值对象之间的相等关系String类是值对象,不可变对象,用equals来比较
{
String s1="a";
//LDC "a" 加载字符串常量到操作数栈
//ASTORE 1 保存字符串常量到变量s1
String s2=s1+"b";//这里调用StringBuffer操作并创建一个String对象
//NEW java/lang/StringBuffer 创建StringBuffer对象
// DUP 复制StringBuffer对象
// ALOAD 1 加载字符变量s1到操作数栈
// INVOKESTATIC java/lang/String.valueOf (Ljava/lang/Object;)Ljava/lang/String;调用String的静态方法valueOf
// INVOKESPECIAL java/lang/StringBuffer.<init> (Ljava/lang/String;)V 调用StringBuffer的构造函数
// LDC "b"加载字符串常量“b”到操作数栈
// INVOKEVIRTUAL java/lang/StringBuffer.append (Ljava/lang/String;)Ljava/lang/StringBuffer;调用SringBuffer的append方法追加字符串“b”
// INVOKEVIRTUAL java/lang/StringBuffer.toString ()Ljava/lang/String;调用StringBuffer的toString方法
// ASTORE 2保存字符串对象到s2变量中
String s3=new String("ab");
//NEW java/lang/String创建String对象
// DUP复制String对象
// LDC "ab"加载字符串常量到操作数栈
// INVOKESPECIAL java/lang/String.<init> (Ljava/lang/String;)V调用String的构造函数
// ASTORE 3保存String对象到变量s3中
String s4=s3+"c";//这里调用StringBuffer操作并创建一个String对象
//NEW java/lang/StringBuffer创建StirngBuffer对象
// DUP复制StringBuffer对象
// ALOAD 3加载变量s3
// INVOKESTATIC java/lang/String.valueOf (Ljava/lang/Object;)Ljava/lang/String;调用String的静态方法valueOf
// INVOKESPECIAL java/lang/StringBuffer.<init> (Ljava/lang/String;)V调用StringBuffer的构造函数
// LDC "c"加载字符串常量到操作数栈
// INVOKEVIRTUAL java/lang/StringBuffer.append (Ljava/lang/String;)Ljava/lang/StringBuffer;调用SringBuffer的append方法追加字符串“c”
// INVOKEVIRTUAL java/lang/StringBuffer.toString ()Ljava/lang/String;调用StringBuffer的toString方法
// ASTORE 4保存字符串对象到s4变量中
System.out.println("ab"==s2);//结果是false,"ab"是字符串常量而s2是String在堆中的对象所以为false
System.out.println(s2+"c"==s4);//结果是false,s2+"c"将产生一个String对象到堆中而s4本身是堆中的一个对象,所以两个对象比较为false
} 通过以上的class指令分析知道:String s2=s1+"b";//是调用stringBuffer操作并创建一个String对象也就是说+操作符使用StringBuffer的append方式实现的最后返回一个新创建的String对象而不是string常量。"a"+"b"等价于"ab",只是生成一个字符串常量,保存在栈中而String s2=s1+"b";保存在堆中。凡是字符串变量与字符串变量或者字符串常量之间使用+都会产生一个String对象到堆中,凡是String s="a"+"b";或者String s="ab";产生一个字符串常量在栈中。
equals 比较值.
如果是字符串的比较建议用equals;
equals 比较值
int a=1;int b=1;
a和b的地址是一样的吗?
你说的是不对的。你可以自己对照内存想想。原生类型和引用类型你不能一概而论。String a ="1";
String b = "1";引用a,引用b.他们在栈中的地址是不一样的。但是他们地址中的内容是一样的,也就是他们指向的是同一对象。所以对于引用类型做==的时候,比较的是他们所指向的对象在内存中的地址是不是一样的。换句话说,指向的是不是同一个对象。对于原生类型。int a = 1;
int b = 1;a和b在JVM栈中的地址是不一样的。而地址中的值是一样的都是1.所以a == b为真。显而易见,比较的值。而非你所说的地址。如果非要下个总结的话。因为不一定都在栈中,所以话不太好说。就用C来描述吧。pa = &a ;pb = &b;比较的是 *pa和*pb对于引用来说,*pa.就是他所指向对象的地址。
对于原生类型来说,*pa就是他的值。
int a;
int b;
}
他俩的地址能一样吗?
==是比较两个所指向的对象是否相同;
equal 是比较两个变量所指向的对象内容是否相同。
你那篇文章我看了,但我感觉那上面说的也欠妥。其实,编译出的字节码就一切可知了。对比一下(1)创建对象public class Test{
public static void main(String[] args){
Cute c = new Cute();
}}看一下与之对应的字节码
public static void main(java.lang.String[] args);
0 new Cute [16]
3 dup
4 invokespecial Cute() [18]
7 astore_1 [c]
8 return(2)String 常量值public class Test{
public static void main(String[] args){
String str = "abc";
String strr = "eee";
String strrr = "abc";
}}
public static void main(java.lang.String[] args);
0 ldc <String "abc"> [16]
2 astore_1 [str]
3 ldc <String "eee"> [18]
5 astore_2 [strr]
6 ldc <String "abc"> [16]
8 astore_3 [strrr]
9 return
(3)基本数据类型public class Test{
public static void main(String[] args){
int a = 5;
int b = 5;
}} public static void main(java.lang.String[] args);
0 iconst_5
1 istore_1 [a]
2 iconst_5
3 istore_2 [b]
4 return以比较局部的角度来看,那么只有(1)(2)与堆内存发生了关系。
(3)没有。而且,istore ,astore.足以说明,我们的引用和基本类型里面存的是什么。而且,(3)没有与常量池发生关系。不知道你满意吗?
http://topic.csdn.net/u/20081123/12/f70f1632-24be-4caa-bc20-29cf8267afab.html?36468在13楼有分析。原始帖子的传播很有意思:新手总结->其他新手认可->传播->一传十十传百->哇塞,真理啊!
其中还有几本书把“java 栈和堆”抄了进去,总之各种给力。
参考地址:http://www.zousky.com/rjkf/java/javase/