黑马程序员技术交流社区
标题:
大虾们 "=="和equals方法究竟有什么区别?
[打印本页]
作者:
于清云
时间:
2012-4-24 17:29
标题:
大虾们 "=="和equals方法究竟有什么区别?
今天看了equals用途,想到了=号 那么"=="和equals方法究竟有什么区别呢?
作者:
周海诚
时间:
2012-4-24 17:31
==操作符专门用来比较变量的值是否相等。比较好理解的一点是:
int a=10;
int b=10;
则a==b将是true。
但不好理解的地方是:
String a=new String("foo");
String b=new String("foo");
则a==b将返回false。
对象变量其实是一个引用,它们的值是指向对象所在的内存地址,而不是对象本身。a和b都使用了new操作符,意味着将在内存中产生两个内容为"foo"的字符串,既然是“两个”,它们自然位于不同的内存地址。a和b的值其实是两个不同的内存地址的值,所以使用"=="操作符,结果会是false。诚然,a和b所指的对象,它们的内容都是"foo",应该是“相等”,但是==操作符并不涉及到对象内容的比较。
对象内容的比较,正是equals方法做的事。
看一下Object对象的equals方法是如何实现的:
boolean equals(Object o){
return this==o;
}
Object对象默认使用了==操作符。所以如果你自创的类没有覆盖equals方法,那你的类使用equals和使用==会得到同样的结果。同样也可以看出,Object的equals方法没有达到equals方法应该达到的目标:比较两个对象内容是否相等。因为答案应该由类的创建者决定,所以Object把这个任务留给了类的创建者。
看一下一个极端的类:
Class Monster{
private String content;
...
boolean equals(Object another){ return true;}
}
我覆盖了equals方法。这个实现会导致无论Monster实例内容
作者:
葛尧
时间:
2012-4-24 17:35
==是关系运算符,返回真或假
equals是方法,在不同的类中有不同的实现,返回值也是自定义的
作者:
王德南
时间:
2012-4-24 17:42
“==”是比较两个对象的地址是否相等,而equals是比较两个对象的内容是否相等。
String a=new String("test");
String b=new String("test");
if(a==b)
{
System.out.println("true");
}
else {
System.out.println("flase");
}
这样的话会输出flase。因为a和b都使用了new操作符,意味着将在内存中产生两个内容为"test"的字符串,既然是“两个”,它们自然位于不同的内存地址。
a和b的值其实是两个不同的内存地址的值,所以使用"=="操作符,结果会是 false。
如果改为if(a.equals(b))
{
System.out.println("true");
}
else {
System.out.println("flase");
}
这样的话就会输出true了。
作者:
韩新凯
时间:
2012-4-24 18:03
这个问题好像已经有人问过了
作者:
光sail
时间:
2012-4-24 18:09
sleep和wait之间的区别:
第一种解释:
功能差不多,都用来进行线程控制,他们最大本质的区别是:sleep()不释放同步锁,wait()释放同步缩.
还有用法的上的不同是:sleep(milliseconds)可以用时间指定来使他自动醒过来,如果时间不到你只能调用interreput()来强行打断;wait()可以用notify()直接唤起.
第二种解释:
sleep是Thread类的静态方法。sleep的作用是让线程休眠制定的时间,在时间到达时恢复,也就是说sleep将在接到时间到达事件事恢复线程执行,例如:
try{
System.out.println("I'm going to bed");
Thread.sleep(1000);
System.out.println("I wake up");
}
catch(IntrruptedException e) {
}
wait是Object的方法,也就是说可以对任意一个对象调用wait方法,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者,例如:
//Thread 1
try{
obj.wait();//suspend thread until obj.notify() is called
}
catch(InterrputedException e) {
}
第三种解释:
这两者的施加者是有本质区别的.
sleep()是让某个线程暂停运行一段时间,其控制范围是由当前线程决定,也就是说,在线程里面决定.好比如说,我要做的事情是 "点火->烧水->煮面",而当我点完火之后我不立即烧水,我要休息一段时间再烧.对于运行的主动权是由我的流程来控制.
而wait(),首先,这是由某个确定的对象来调用的,将这个对象理解成一个传话的人,当这个人在某个线程里面说"暂停!",也是 thisOBJ.wait(),这里的暂停是阻塞,还是"点火->烧水->煮饭",thisOBJ就好比一个监督我的人站在我旁边,本来该线 程应该执行1后执行2,再执行3,而在2处被那个对象喊暂停,那么我就会一直等在这里而不执行3,但正个流程并没有结束,我一直想去煮饭,但还没被允许, 直到那个对象在某个地方说"通知暂停的线程启动!",也就是thisOBJ.notify()的时候,那么我就可以煮饭了,这个被暂停的线程就会从暂停处 继续执行.
其实两者都可以让线程暂停一段时间,但是本质的区别是一个线程的运行状态控制,一个是线程之间的通讯的问题
在java.lang.Thread类中,提供了sleep(),
而java.lang.Object类中提供了wait(), notify()和notifyAll()方法来操作线程
sleep()可以将一个线程睡眠,参数可以指定一个时间。
而wait()可以将一个线程挂起,直到超时或者该线程被唤醒。
wait有两种形式wait()和wait(milliseconds).
sleep和wait的区别有:
1,这两个方法来自不同的类分别是Thread和Object
2,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3,wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在
任何地方使用
synchronized(x){
x.notify()
//或者wait()
}
4,sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
作者:
光sail
时间:
2012-4-24 18:28
问题看错了,sorry
作者:
光sail
时间:
2012-4-24 18:36
由于网络延迟原因,上面发生了误会,不好意思,
==和equal的区别 : ==比较的是变量指向的对象在内存中的地址是否一样,equal比较的变量的toString
()方法后返回的字符串内容是否相同
作者:
龚正军
时间:
2012-4-24 18:50
最开始“==”和“equals"其实是一个意思,因为equals的英文意思就是等价的意思!!
但是问题来了。当遇到很多时候我们在java中比较2个对象或则数据的时候,我们不得不面对内存地址的问题。
因为任何数据都必须依靠内存二存在。所以当我们用"=="和“equals"的时候就不得不面对当2个不同对象(有不同地址,2个独立的对象),但他们数据是一样(比如都是数值54)的时候,
我们会得到一个莫名其妙的结果:false,(不对)。什么??明明就是都是数值54,世界人民都知道是相等的,为什么比较就不对了难??(虽然我们都知道是因为地址不一样的2个独立对象造成的问题)------------------------
------------------割了还会有的--------------------
所以java工程师就把"equals"复写掉了,把它原来的意思在很多只需要对比实际数值是否相同或则实际是否一样的情况下就判定为:true(正确)。
所以就得到了:"=="是2个对象进行比较,他们会对比内存地址。
"equals"是2个对象的数值(或则数据等等)进行不叫,不会再对比内存地址了。
不知道能帮助你理解了不?????
作者:
程序猿
时间:
2012-4-24 18:50
本帖最后由 欧阳梦南 于 2012-4-24 18:52 编辑
内存空间中有栈内存和堆内存。
如果用‘==’运算符进行比较的话,需要使用8种基本数据类型。因为8种基本数据类型是存在栈中。
而String类等非基本数据类型存储形式是不同的,String s=new String("hello")
前面的String s ,s是在栈内存中,new String("hello")的"hello"是在堆内存中。s保存的的指向堆内存hello的地址。当你创建两个String对象的时候。
这时再创建一个String对象,String s2=new String("hello"). 此时的new String("hello"). 的hello存放位置和之前的hello存放的地址是不同的。此时s1和s2指向的是不同的堆内存地址(虽然堆内存这两个空间都是hello)。此时s1==s2,判断的是s1、s2指向的地址是否相等。而此时我们是想比较实例化的值是否相等,就需要用s1.equals(s2)来判断了
作者:
程序猿
时间:
2012-4-24 18:51
内存空间中有栈内存和堆内存。
如果用‘==’运算符进行比较的话,需要使用8种基本数据类型。因为8种基本数据类型是存在栈中。
而String类等非基本数据类型存储形式是不同的,String s=new String("hello")
前面的String s ,s是在栈内存中,new String("hello")的"hello"是在堆内存中。s保存的的指向对内存hello的地址。当你创建两个String对象的时候。
这时再创建一个String对象,String s2=new String("hello"). 此时的new String("hello"). 的hello存放位置和之前的hello存放的地址是不同的。此时s1和s2指向的是不同的堆内存地址(虽然堆内存这两个空间都是hello)。此时s1==s2,判断的是s1、s2指向的地址是否相等。而此时我们是想比较实例化的值是否相等,就需要用s1.equals(s2)来判断了
作者:
xiwangliujiao
时间:
2012-4-24 19:57
一般比较字符串是否相等时用equals的,==比较的是内存地址是否相同。
作者:
newlaw2013
时间:
2012-4-24 21:16
关键词:字符串常量池,字符串常量缓冲区:
/*
在java中,String是字符串常量。有相同序列的字符组成的两个字符串属于同一对象,位于内存中的同一个位置,即字符串常量缓冲区,也叫字符串常量池。每个字符串常量只有一个String对象来表示。即使这个字符串常量出现在一个程序的不同位置甚至一个程序的不同程序包中。
--------------
说明:
★s1+s2此时所创建的"hello",作为String对象存储在内存中的一个独立位置,它还不在字符串常量池中。
--------------
☆intern()方法把运行时产生的字符串(s1+s2)加到字符串常量池中,如果池中已经有了和(s1+s2)相同的String对象,则不添加,否则会添加。这里的hello显然已存在字符串常量池中,s1+s2没有必要再次添加
进去(也添加不了重复的字符串),只需要从常量池拿着用就可以了。
--------------
△用new创建对象时,必然会再堆内存中开辟新的空间(即分配新的内存地址),所以每一次new,都会创建一个新的空间。==比较的是地址,新new的内存空间地址肯定不一样,所以是false。equals比较是其中的内容是否一致,内容都是字符串常量池中的"hello",是一样的,所以返回true。
*/
class A
{
public static String strA = "darkhorse";
}
class B
{
public static String strB = "darkhorse";
}
class C
{
public static String strC ="dark"+"horse";
}
class Test
{
public static void main(String[] args)
{
sop("A.strA==B.strB : "+(A.strA==B.strB));//true
sop("A.strA==C.strC : "+(A.strA==C.strC));//true
String s1 = "dark";
String s2 = "horse";
sop(A.strA==(s1+s2));//★false: 见说明。
sop(A.strA==(s1+s2).intern());//☆true:见说明。
//以下的例子供参考:
String str1 = "hello";
String str2 = "hello";
sop("str1==str2 : "+(str1==str2));//true
String str3 = new String("hello");
String str4 = new String ("hello");
sop("str3==str4 : "+(str3==str4));//△false:见说明。
sop("str3.equals(str4) : "+str3.equals(str4));//△true:见说明。
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
复制代码
作者:
孙天
时间:
2012-4-27 21:48
"=="和equals方法的区别
(单独把一个东西说清楚,然后再说清楚另一个,这样,它们的区别自然就出来了,混在一起说,则很难说清楚)
==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。
如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。
equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:
String a=new String("foo");
String b=new String("foo");
两条new语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。
在实际开发中,我们经常要比较传递进行来的字符串内容是否等,例如,String input = …;input.equals(“quit”),许多人稍不注意就使用==进行比较了,这是错误的,随便从网上找几个项目实战的教学视频看看,里面就有大量这样的错误。记住,字符串的比较基本上都是使用equals方法。
如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下:
boolean equals(Object o){
return this==o;
}
这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2