ava에서 같음과 ==의 차이점은 값 유형이 메모리에 저장된 스택(줄여서 스택)인 반면, 참조 유형 변수는 참조 유형 변수의 주소만 스택에 저장하는 반면 그 자체는 힙에 저장됩니다.
== 연산은 두 변수의 값이 같은지 비교하는 것입니다. 참조 변수의 경우 두 변수의 힙에 저장된 주소가 같은지, 즉 스택의 내용이 같은지 여부를 의미합니다. 동일합니다.
equals 연산으로 표현되는 두 변수가 동일한 객체에 대한 참조인지, 즉 힙의 내용이 동일한지 여부입니다.
==는 두 객체의 주소를 비교하고, equals는 두 객체의 내용을 비교합니다.
분명히, 같음이 참일 때 ==는 반드시 참이 아닙니다.
1. 문자열
Java 코드에서 ==는
public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = "Monday"; } }
위 프로그램에 객체가 있나요?
테스트해보고 프로그램을 살짝 바꿔보겠습니다
Java 코드
public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = "Monday"; if (s1 == s2) System.out.println("s1 == s2"); else System.out.println("s1 != s2"); } }
프로그램을 컴파일하고 실행하면 출력: s1 == s2
설명: s1 및 s2는 동일한 문자열 객체를 참조합니다 - "Monday"!
2.
프로그램을 약간 변경하면 더욱 이상한 점을 발견할 수 있습니다.
Java 코드
public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = new String("Monday"); if (s1 == s2) System.out.println("s1 == s2"); else System.out.println("s1 != s2"); if (s1.equals(s2)) System.out.println("s1 equals s2"); else System.out.println("s1 not equals s2"); } }
새 연산자를 사용하여 s2를 만듭니다.
프로그램 출력:
s1 != s2
s1 = s2
설명: s1 및 s2는 두 개의 "월요일" 문자열 개체를 참조합니다. 각각
3. 문자열 버퍼 풀
프로그램이 실행되면 문자열 버퍼 풀이 생성되는 것으로 나타났습니다.
s2 = "Monday"와 같은 표현식을 사용하면 문자열 가 생성되면 프로그램은 먼저
이 문자열 버퍼 풀에서 동일한 값을 가진 객체를 찾습니다. 첫 번째 프로그램에서는 s1이 먼저 풀에 들어가므로
s2가 생성되면 프로그램이 찾습니다. 동일한 값을 가진 객체
는 s2를 s1이 참조하는 "월요일" 객체를 참조합니다.
두 번째 프로그램에서는 new 연산자가 사용되어 프로그램에 다음과 같이 명확하게 알려줍니다. 새로운 것을 원해요! "그래서 새로운 "월요일" Sting 개체가 메모리에 생성됩니다. 가치관은 같지만 위치가 다릅니다. 하나는 수영장에서 수영하고
다른 하나는 해변에서 쉬고 있습니다. 이런, 자원 낭비가 분명합니다. 왜 분명히 동일할 때 분리해야 합니까?
4.
프로그램 다시 변경:
Java 코드
public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = new String("Monday"); s2 = s2.intern(); if (s1 == s2) System.out.println("s1 == s2"); else System.out.println("s1 != s2"); if (s1.equals(s2)) System.out.println("s1 equals s2"); else System.out.println("s1 not equals s2"); } }
这次加入:s2 = s2.intern();
程序输出:
s1 == s2
s1 equals s2
原来,(java.lang.String的intern()方法
"abc".intern()方法的返回值还是字符串"abc",表面上看起来好像这个方法没什么用处。但实际上,它做了个小动作:
检查字符串池里是否存在"abc"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会把"abc"添加到字符串池中,然后再返回它的引用。
)
更好的办法:
把所有的String都intern()到缓冲池去吧
最好在用到new的时候就进行这个操作
String s2 = new String("Monday").intern();
然后就可以用==比较两个字符串的值了
二、简单数据类型和封装类中的equals和==
Java为每一个简单数据类型提供了一个封装类,每个基本数据类型可以封装成对象类型。
除int(Integer)和char(Character),其余类型首字母大写即成封装类类型名。double (Double), float(Float),long(Long), short(Short),byte(Byte),boolean(Boolean).
以int和Integer为例说明
Java中int和Integer区别如下:
1.int是基本的数据类型,默认值可以为0;
2.Integer是int的封装类,默认值为null;
3.int和Integer都可以表示某一个数值;
4.int和Integer不能够互用,因为他们两种不同的数据类型;
int a1=1;
int a2=1;
Integer b1 =new Integer (1);
Integer b2 =new Integer (1);
------------------------------
a1==a2 这个是成立的,很简单,都知道
a1==b1 这个是不成立的.表达式的值为 false ,它们是不同的数据类型(在jdk1.5以上版本中为true)
b1==b2 这个也是不成立的.表达式的值为 false,虽然是相同的数据类型,但是它们是两个对象,==比较的是2个对象的地址,它们的地址是不相等的,内容相等都是1;
b1.equals(b2)==true 这个是成立的,表达式的值为 true. 相同数据类型,两个对象,地址不同,内容相同, quals比较的是2个对象的内容,所以成立。
(a.equals(b),因为equals比较的是两个对象,所以a,b都不能为基本数据类型,否则会出编译错误。)(在jdk1.5以上版本中,b可以为基本数据类型,a不可以)
同理,其它的封装类和基本类型也是这样的.
java中equals和==的区别
==比较的是2个对象的地址,而equals比较的是2个对象的内容。
在jdk1.5以上的版本中,基本类型和封装类能自动转化,与String类型的对象和字符串常量类似。
Java代码
Integer i1 = 123; Integer i2 = 123; int i = 123; Integer i3 = new Integer(123); Integer i4 = new Integer(123); System.out.println("i1 == i2 = "+(i1 == i2)); System.out.println("i1.equals(i2) = "+(i1.equals(i2))); System.out.println(); System.out.println("i3 == i4 = "+(i3 == i4)); System.out.println("i3.equals(i4) = "+(i3.equals(i4))); System.out.println(); System.out.println("i2 == i4 = "+(i2 == i4)); System.out.println("i2.equals(i4) = "+(i2.equals(i4))); System.out.println(); System.out.println("i == i2 = "+(i == i2)); System.out.println("i1.equals(i) = "+(i1.equals(i))); System.out.println(); System.out.println("i == i4 = "+(i == i4)); System.out.println("i4.equals(i) = "+(i4.equals(i))); ------------------------------ i1 == i2 = true i1.equals(i2) = true i3 == i4 = false i3.equals(i4) = true i2 == i4 = false i2.equals(i4) = true i == i2 = true i1.equals(i) = true i == i4 = true i4.equals(i) = true
三、其他类怎么使用equals和==
API里的类大部分都重写了equals方法,没有重写的一般是自己写的类,
如果是你自己定义的一个类,比较自定义类用equals和==是一样的,都是比较句柄地址,
因为自定义的类是继承于object,而object中的equals就是用==来实现的,你可以看源码。
四、java里equals和hashCode之间什么关系
只是为了维护 hashCode 方法的常规协定,才要求用equals比较的两个对象的hashCode相同.
equals()和hashCode()都来自java.lang.Object.你当然可以重写.
比如a.equals(b).仅当a的内存地址相等时,才返回true.当然如String等类已经对这个方法进行了重写,比较的就不再是内存地址了.
hashCode()的值也是与内存地址相关的.所以仅当内存地址相等时,hashCode才相等.
同样很多类也重写了这个方法,还是以String为例:
Java代码
public int hashCode() { int h = hash; if (h == 0) { int off = offset; char val[] = value; int len = count; for (int i = 0; i < len; i++) { h = 31*h + val[off++]; } hash = h; } return h; }
就不在与内存地址相关了.这样做是为了保证用equals比较返回为true的两个对象,他们的hashCode是相同的.
所以一般重写equals的时候都会重写hashCode().
当然,这个相当于一个约定,一个协议.你不这么做并不会错.
五、hashCode
在一般的应用中你不需要了解hashcode的用法,但当你用到hashmap,hashset等集合类时要注意下hashcode。
你想通过一个object的key来拿hashmap的value,hashmap的工作方法是,
通过你传入的object的hashcode在内存中找地址,
当找到这个地址后再通过equals方法来比较这个地址中的内容是否和你原来放进去的一样,一样就取出value。
所以这里要匹配2部分,hashcode和equals
但假如说你new一个object作为key去拿value是永远得不到结果的,
因为每次new一个object,这个object的hashcode是永远不同的,所以我们要重写hashcode,
你可以令你的hashcode是object中的一个恒量,这样永远可以通过你的object的hashcode来找到key的地址,
然后你要重写你的equals方法,使内存中的内容也相等。。。
更多java中equals和==的区别相关文章请关注PHP中文网!