在java编程或者面试中经常会遇到 == 、equals()的比较。自己看了看源码,结合实际的编程总结一下。

1. == 

  java中的==是比较两个对象在JVM中的地址。比较好理解。看下面的代码:

1 public class ComAddr{
2 public static void main(String[] args) throws Exception {
3 String s1 = "nihao";
4 String s2 = "nihao";
5 String s3 = new String("nihao");
6 System.out.println(s1 == s2); // true
7 System.out.println(s1 == s3); // false
8 }
9 }

  上述代码中:

  (1)s1 == s2为true,是因为s1和s2都是字符串字面值"nihao"的引用,指向同一块地址,所以相等。

  (2)s1 == s3为false,是因为通过new产生的对象在堆中,s3是堆中变量的引用,而是s1是指向字符串字面值"nihao"的引用,地址不同所以不相等。

2.equals()

  equals是根类Obeject中的方法。源代码如下:

public boolean equals(Object obj) {
return (this == obj);
}

  可见默认的equals方法,直接调用==,比较对象地址。

  不同的子类,可以重写此方法,进行两个对象的equals的判断。

  String类源码中重写的equals方法如下,

 1     public boolean equals(Object anObject) {
2 if (this == anObject) {
3 return true;
4 }
5 if (anObject instanceof String) {
6 String anotherString = (String) anObject;
7 int n = value.length;
8 if (n == anotherString.value.length) {
9 char v1[] = value;
10 char v2[] = anotherString.value;
11 int i = 0;
12 while (n-- != 0) {
13 if (v1[i] != v2[i])
14 return false;
15 i++;
16 }
17 return true;
18 }
19 }
20 return false;
21 }

  从上面的代码中可以看到,

  (1)String类中的equals首先比较地址,如果是同一个对象的引用,可知对象相等,返回true。

  (2)若果不是同一个对象,equals方法挨个比较两个字符串对象内的字符,只有完全相等才返回true,否则返回false。

3.hashcode()

  hashCode是根类Obeject中的方法。

  默认情况下,Object中的hashCode() 返回对象的32位jvm内存地址。也就是说如果对象不重写该方法,则返回相应对象的32为JVM内存地址。

  String类源码中重写的hashCode方法如下,

 1 public int hashCode() {
2 int h = hash; //Default to 0 ### String类中的私有变量,
3 if (h == 0 && value.length > 0) { //private final char value[]; ### Sting类中保存的字符串内容的的数组
4 char val[] = value;
5
6 for (int i = 0; i < value.length; i++) {
7 h = 31 * h + val[i];
8 }
9 hash = h;
10 }
11 return h;
12 }

  String源码中使用private final char value[];保存字符串内容,因此String是不可变的。

  看下面的例子,没有重写hashCode方法的类,直接返回32位对象在JVM中的地址;Long类重写了hashCode方法,返回计算出的hashCode数值:

 1 public class ComHashcode{
2 public static void main(String[] args) throws Exception {
3 ComHashcode a = new ComHashcode();
4 ComHashcode b = new ComHashcode();
5 System.out.println(a.hashCode()); //870919696
6 System.out.println(b.hashCode()); //298792720
7
8 Long num1 = new Long(8);
9 Long num2 = new Long(8);
10 System.out.println(num1.hashCode()); //8
11 System.out.println(num2.hashCode()); //8
12 }
13 }

总结:

(1)绑定。当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

(2)绑定原因。Hashtable实现一个哈希表,为了成功地在哈希表中存储和检索对象,用作键的对象必须实现 hashCode 方法和 equals 方法。同(1),必须保证equals相等的对象,hashCode 也相等。因为哈希表通过hashCode检索对象。

(3)默认。

  ==默认比较对象在JVM中的地址。

  hashCode 默认返回对象在JVM中的存储地址。

  equal比较对象,默认也是比较对象在JVM中的地址,同==

参考:

http://docs.oracle.com/javase/7/docs/api/

java中的==、equals()、hashCode()源码分析

在java编程或者面试中经常会遇到 == 、equals()的比较。自己看了看源码,结合实际的编程总结一下。

1. == 

  java中的==是比较两个对象在JVM中的地址。比较好理解。看下面的代码:

1 public class ComAddr{
2 public static void main(String[] args) throws Exception {
3 String s1 = "nihao";
4 String s2 = "nihao";
5 String s3 = new String("nihao");
6 System.out.println(s1 == s2); // true
7 System.out.println(s1 == s3); // false
8 }
9 }

  上述代码中:

  (1)s1 == s2为true,是因为s1和s2都是字符串字面值"nihao"的引用,指向同一块地址,所以相等。

  (2)s1 == s3为false,是因为通过new产生的对象在堆中,s3是堆中变量的引用,而是s1是指向字符串字面值"nihao"的引用,地址不同所以不相等。

2.equals()

  equals是根类Obeject中的方法。源代码如下:

public boolean equals(Object obj) {
return (this == obj);
}

  可见默认的equals方法,直接调用==,比较对象地址。

  不同的子类,可以重写此方法,进行两个对象的equals的判断。

  String类源码中重写的equals方法如下,

 1     public boolean equals(Object anObject) {
2 if (this == anObject) {
3 return true;
4 }
5 if (anObject instanceof String) {
6 String anotherString = (String) anObject;
7 int n = value.length;
8 if (n == anotherString.value.length) {
9 char v1[] = value;
10 char v2[] = anotherString.value;
11 int i = 0;
12 while (n-- != 0) {
13 if (v1[i] != v2[i])
14 return false;
15 i++;
16 }
17 return true;
18 }
19 }
20 return false;
21 }

  从上面的代码中可以看到,

  (1)String类中的equals首先比较地址,如果是同一个对象的引用,可知对象相等,返回true。

  (2)若果不是同一个对象,equals方法挨个比较两个字符串对象内的字符,只有完全相等才返回true,否则返回false。

3.hashcode()

  hashCode是根类Obeject中的方法。

  默认情况下,Object中的hashCode() 返回对象的32位jvm内存地址。也就是说如果对象不重写该方法,则返回相应对象的32为JVM内存地址。

  String类源码中重写的hashCode方法如下,

 1 public int hashCode() {
2 int h = hash; //Default to 0 ### String类中的私有变量,
3 if (h == 0 && value.length > 0) { //private final char value[]; ### Sting类中保存的字符串内容的的数组
4 char val[] = value;
5
6 for (int i = 0; i < value.length; i++) {
7 h = 31 * h + val[i];
8 }
9 hash = h;
10 }
11 return h;
12 }

  String源码中使用private final char value[];保存字符串内容,因此String是不可变的。

  看下面的例子,没有重写hashCode方法的类,直接返回32位对象在JVM中的地址;Long类重写了hashCode方法,返回计算出的hashCode数值:

 1 public class ComHashcode{
2 public static void main(String[] args) throws Exception {
3 ComHashcode a = new ComHashcode();
4 ComHashcode b = new ComHashcode();
5 System.out.println(a.hashCode()); //870919696
6 System.out.println(b.hashCode()); //298792720
7
8 Long num1 = new Long(8);
9 Long num2 = new Long(8);
10 System.out.println(num1.hashCode()); //8
11 System.out.println(num2.hashCode()); //8
12 }
13 }

总结:

(1)绑定。当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

(2)绑定原因。Hashtable实现一个哈希表,为了成功地在哈希表中存储和检索对象,用作键的对象必须实现 hashCode 方法和 equals 方法。同(1),必须保证equals相等的对象,hashCode 也相等。因为哈希表通过hashCode检索对象。

(3)默认。

  ==默认比较对象在JVM中的地址。

  hashCode 默认返回对象在JVM中的存储地址。

  equal比较对象,默认也是比较对象在JVM中的地址,同==

参考:

http://docs.oracle.com/javase/7/docs/api/\

http://www.cnblogs.com/xudong-bupt/p/3960177.html

java中的==、equals()、hashCode()源码分析(转载)的更多相关文章

  1. JAVA设计模式-动态代理(Proxy)源码分析

    在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现. 一,Proxy.newProxyInstance方法 @Cal ...

  2. java集合系列之LinkedList源码分析

    java集合系列之LinkedList源码分析 LinkedList数据结构简介 LinkedList底层是通过双端双向链表实现的,其基本数据结构如下,每一个节点类为Node对象,每个Node节点包含 ...

  3. java集合系列之ArrayList源码分析

    java集合系列之ArrayList源码分析(基于jdk1.8) ArrayList简介 ArrayList时List接口的一个非常重要的实现子类,它的底层是通过动态数组实现的,因此它具备查询速度快, ...

  4. RocketMQ中Broker的启动源码分析(二)

    接着上一篇博客  [RocketMQ中Broker的启动源码分析(一)] 在完成准备工作后,调用start方法: public static BrokerController start(Broker ...

  5. java多线程系列(九)---ArrayBlockingQueue源码分析

    java多线程系列(九)---ArrayBlockingQueue源码分析 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 j ...

  6. Java集合系列[4]----LinkedHashMap源码分析

    这篇文章我们开始分析LinkedHashMap的源码,LinkedHashMap继承了HashMap,也就是说LinkedHashMap是在HashMap的基础上扩展而来的,因此在看LinkedHas ...

  7. Java并发系列[2]----AbstractQueuedSynchronizer源码分析之独占模式

    在上一篇<Java并发系列[1]----AbstractQueuedSynchronizer源码分析之概要分析>中我们介绍了AbstractQueuedSynchronizer基本的一些概 ...

  8. Java并发系列[3]----AbstractQueuedSynchronizer源码分析之共享模式

    通过上一篇的分析,我们知道了独占模式获取锁有三种方式,分别是不响应线程中断获取,响应线程中断获取,设置超时时间获取.在共享模式下获取锁的方式也是这三种,而且基本上都是大同小异,我们搞清楚了一种就能很快 ...

  9. Java并发系列[5]----ReentrantLock源码分析

    在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可 ...

随机推荐

  1. css左右布局,左侧固定,右侧自适应

    实现布局的几种方法,见代码: <!DOCTYPE html> <html lang="cn"> <head> <meta charset= ...

  2. git已经删除了远程分支,本地仍然能看到

    1.使用 git branch -a 命令可以查看所有本地分支和远程分支,发现很多在远程仓库已经删除的分支在本地依然可以看到. 2.使用命令 git remote show origin,可以查看re ...

  3. 关于npm run dev报错npm ERR! missing script: dev

    出现这个问题应当重新使用 vue init webpack 来初始化工程. 在执行 npm run dev 就可以执行了.

  4. 最近用.NET实现DHT爬虫,全.NET实现

    最近用.NET实现DHT爬虫,全.NET实现,大家可以加我QQ交流下  309159808

  5. LARTC

    大牛的博客 howto ,however, is simplify. another space ip link list ip address show ip route show route -n ...

  6. 蓝桥杯-正则问题(dfs,解决()的计算)

    历届试题 正则问题   时间限制:1.0s   内存限制:256.0MB      问题描述 考虑一种简单的正则表达式: 只由 x ( ) | 组成的正则表达式. 小明想求出这个正则表达式能接受的最长 ...

  7. windows下python3.7.2内置venv虚拟环境下pyinstaller错误问题

    起因 开发一直使用python -m venv .pyenv 方式创建虚拟环境,在利用pyinstaller打包发布应用时,出现错误 3178 INFO: Warnings written to C: ...

  8. Python开发:Windows下Python+Eclipse+Pydev开发环境配置

    一.配置前的准备: 1.安装jdk: 下载地址: https://www.oracle.com/technetwork/java/javase/downloads/index.html 2.安装Ecl ...

  9. 关于Java 下 Snappy压缩存文件

    坑点: 压缩后的byte 数组中会有元素是负数,如果转化成String 存入文件,然后再读取解压缩还原,无法得到原来的结果,甚至是无法解压缩. 原因分析: String 底层是由char 数组构成的, ...

  10. Golang之并发资源竞争(互斥锁)

    并发本身并不复杂,但是因为有了资源竞争的问题,就使得我们开发出好的并发程序变得复杂起来,因为会引起很多莫名其妙的问题. package main import ( "fmt" &q ...