青岛网站备案,html网页制作视频教学,交互设计师和ui设计师的区别,北京建筑公司一览表一、 运算符 是 Java 中的一个运算符#xff0c;用于比较两个对象#xff0c;但在比较两个对象的时候需要根据比较类型分情况进行讨论。
1.1 基本数据类型与基本数据类型
基本数据类型之间通过 进行比较的时候#xff0c;是直接比较它们的大小#xff0c;而与它们的具体…一、 运算符 是 Java 中的一个运算符用于比较两个对象但在比较两个对象的时候需要根据比较类型分情况进行讨论。
1.1 基本数据类型与基本数据类型
基本数据类型之间通过 进行比较的时候是直接比较它们的大小而与它们的具体类型无关。
short num1 20000;
int num2 20000;
System.out.println(num1 num2); // Output: true
1.2 引用类型与引用类型
引用类型之间是比较它们的内存地址因此两个同类型的对象通过 进行比较时的结果一般为 false。
public class Test {public static void main(String[] args) {Obj o1 new Obj();Obj o2 new Obj();System.out.println(o1 o2); // Output: false}
}class Obj {}
但也不是所有情况都会返回 false基本数据类型的引用类型有个常量池的机制使得它们就算是两个对象依然会指向同一片内存空间也就是说它们依然是同一个对象。
Integer num1 100, num2 100;
System.out.println(num1 num2); // Output: true
具体内容请见八大基本类型及其包装类型
1.3 基本数据类型与引用类型
当基本数据类型与引用类型之间进行比较时若引用类型是数字类的那么就可以进行比较其他类型的无法进行比较会报错。
Integer num1 200;
int num2 200;
System.out.println(num1 num2); // Output: trueint num 200;
String str 123;
System.out.println(str num); // Error: 二元运算符 的操作数类型错误
二、equals 方法
equals 是 Java 引用类型的一个基本方法在没有对其进行重写override的情况下equals 方法默认是比较两个对象的内存地址重写之后视具体情况而定。
String str1 1;
String str2 2;
System.out.println(str1.equals(str2)); // Output: false
2.1 equals 方法和 运算符的区别 是一个运算符equals 是对象的方法所以基本数据类型没有 在比较基本数据类型时是比较的值比较对象的时候是比较其内存地址equals 默认没有被重写是比较对象的内存地址重写后是其他的内容如 String 就是其对象所表示内容的值
三、hashcode 方法
hashcode 是一个非常特殊的方法它涉及到散列表的知识哈希hash翻译过来就是散列的意思它是一种算法可以快速将任意对象转换为一个 16 进制的数值而不同的对象之间通过哈希算法得到的哈希值大概率是不会相同的有极小概率会相同此时就出现了一种被称为“哈希冲突”的情况这里我们不对其做深究具体内容请参见哈希算法
总之在没有出现“哈希冲突”的情况下我们就可以通过不同对象的哈希值不相同这一特性来判断两个对象是否为同一对象。
String str1 1;
String str2 2;
System.out.println(str1.hashCode() str2.hashCode()); // Output: false
当然一般情况下我们是不会像上面这样用 hashcode 这一方法的因为无法保证不会出现“哈希冲突”的情况。虽然不同对象的哈希值有可能相同但是两个对象的哈希值的不同则说明它们一定不相同因此哈希值可以用于判断两个对象是否不等。
四、区别和联系
4.1 区别 一般用来判断数字是否相等equals 一般用来判断两个对象是否相等而 hashcode 一般用来判断两个对象是否不等。 只比较数字判断速度最快此外是 hashcode 方法因为哈希值的计算十分快速最后是 equals默认情况下 equals 是比较两个对象的内存地址这一过程虽然很快速但更一般的情况是 equals 方法被重写了比较的是两个非数字类型对象的属性值因此它最慢。
String str1 1;
String str2 1;
System.out.println(str1.equals(str2)); // Output: true
上面的代码中Java 内置引用类型 String 就重写了 equals 方法它比较的是两个 String 对象的内容而非内存地址。
4.2 联系 一般和 equals 和 hashcode 扯不上什么关系从某种角度上来说equals 和 hashcode 之间也没有必然联系。但是 Java 中存在一种数据结构将 equals 和 hashcode 联系了起来那就是 HashMap 及其子类。
HashMap 中键是不可以重复的因此它的键就必须是不同的对象那么这个时候就先用计算速度快的 hashcode 进行比较若哈希值都不相等那么这两个对象必然不相等若是相等的那么这个就有两种可能出现一种情况是这两个对象是真的相等另外一种情况就是出现了罕见的“哈希冲突”现象那么这个时候就轮到 equals 来进行判断了这样一来就高效且快速地解决了键不可重复的问题。
从上面 HashMap 的比较中我们也可以看到当我们自定义类型的时候若要重写 equals 方法或者 hashcode 方法请将它们两个同时进行重写因为 Java 内置数据结构 HashMap 等判断键是否重复是需要同时调用它们两个。
综上我们可以总结为下表
比较方式 运算符equals 方法hashcode 方法比较速度快速默认情况下快速一般情况下缓慢中等比较值数值默认是内存地址一般是对象属性哈希值
4.3 经典问题
为什么重写了 hashcode 方法还要重写 equals 方法如果只重写 equals 方法而不重写 hashcode 方法会有问题吗在 HashMap 中怎样体现出来的
在 HashMap 中键是不可以重复的也就是说它们的键都是不相同的因此就要判断不同对象是否为同一对象。为了解决这个问题HashMap 中同时调用了对象的 equals 方法和 hashcode 方法来进行判断。判断的部分源代码是这样的
if (e.hash hash ((k e.key) key || (key ! null key.equals(k))))return e;
hashcode 方法和 equals 方法都可以用来比较两个对象但是二者有一些区别
比较方式equals 方法hashcode 方法比较速度 默认情况比较内存地址速度快 重写后一般比较内容速度慢 计算哈希值速度快比较值内存地址或者内容属性哈希值
因此先用计算速度快的 hashcode 进行比较这可以解决大部分问题但由于可能出现“哈希冲突”于是还需要 equals 方法解决。
正因为在判断键是否重复这一问题需要同时调用 equals 方法和 hashcode 方法故我们自己定义的类中重写它们时必须两个一起重写。若只重写 equals 方法而不重写 hashcode 方法那么创建两个内容一样但内存地址不同的对象并存储在 HashMap 中时会被当成两个键而不是一个键进而引发其他错误。