Object 类是 Java 中所有类的始祖,在 Java 中每个类都是由它扩展而来的,我来为大家科普一下关于java hashcode是什么?下面希望有你要的答案,我们一起来看看吧!
java hashcode是什么
Object 类是 Java 中所有类的始祖,在 Java 中每个类都是由它扩展而来的。
在 Java 中,只有基本类型 ( primitive types) 不是对象, 例如,数值、 字符和布尔类型的 值都不是对象。 所有的数组类型,不管是对象数组还是基本类型的数组都扩展了 Object 类。
equals 方法
Object 类中的 equals 方法用于检测一个对象是否等于另外一个对象。
public class Employee{ public boolean equals(Object otherObject){ if(this == otherObject) return true; if(otherObject == null) return false; if(getClass() != otherObject.getClass()){ return false; } Employee other = (Employee) otherObject; return name.equals(other.name)&&salary == other.salary && hireDay.equals(other.hireDay); } }
在子类中定义 equals 方法时, 首先调用超类的 equals。如果检测失败, 对象就不可能相 等。如果超类中的域都相等, 就需要比较子类中的实例域。
public class Manager extends Employee{ public boolean equals(Object otherObject){ if(!super.equals(otherObject))return false; Manager other = (Manager) otherObject; return bonus == other.bonus; } }
这里提到一个问题:许多程序员喜欢使用 instanceof 进行检测:
if ( otherObject instanceof Employee)) return false; 这个如果是在上面的情况下替代if(getClass() != otherObject.getClass())是没什么影响,但是由于Java 语言规范要求 equals 方法具有:对称性---对于任何引用 x、 y 和 z, 如果 x.equals(y) 返 N true, y.equals(z) 返回 true, x.equals(z) 也应该返回 true。 这里可能就会在Manager如果定义了自己的equals方法的情况下出现问题:比如
e. equals(m) 这里的 e 是一个 Employee 对象, m 是一个 Manager 对象, 并且两个对象具有相同的姓名、 薪水和雇佣日期。 如果在 Employee.equals 中用 instanceof 进行检测, 则返回 true, . 然而这意 味着反过来调用: m .equals(e) 也需要返回 true、 对称性不允许这个方法调用返回 false(不过这里如果还是调用if ( otherObject instanceof Employee)) return false; 也没什么问题就怕变成if ( otherObject instanceof Manager)) return false; ),或者抛出异常: 这就使得 Manager 类受到了束缚。 这个类的 equals 方法必须能够用自己与任何一 个 Employee 对象进行比较, 而不考虑经理拥有的那部分特有信息!
所以:
- 如果子类能够拥有自己的相等概念, 则对称性需求将强制采用 getClass 进行检测;
- 如果由超类决定相等的概念,那么就可以使用 imtanceof进行检测, 这样可以在不同 子类的对象之间进行相等的比较。
hashCode 方法
散列码( hash code ) 是由对象导出的一个整型值。散列码是没有规律的。如果 x 和 y 是 两个不同的对象, x.hashCode( ) 与 y.hashCode( ) 基本上不会相同。
// String 类使用下列算法计算散列码 int hash = 0; for(int i = 0; i<length();i ){ hash = 31*hash charAt(i); }
由于 hashCode方法定义在 Object 类中, 因此每个对象都有一个默认的散列码,其值为 对象的存储地址。(所以String类中重写了hashCode()),看下面例子:
String s = "ok"; StringBuilder sb = new StringBuilder(s); System.out.println(s.hashCode() " " sb.hashCode()); String t = new String("ok"); StringBuilder tb = new StringBuilder(t); System.out.println(t.hashCode() " " tb.hashCode());
字符串 s 与 t 拥有相同的散列码, 这是因为字符串的散列码是由内容导出 的。而字符串缓冲 sb 与 tb却有着不同的散列码, 这是因为在 StringBuffer 类中没有定义 hashCode 方法,它的散列码是由 Object 类的默认 hashCode 方法导出的对象存储地址。 如果重新定义 equals方法,就必须重新定义 hashCode 方法, 以便用户可以将对象插入到散列表中。
需要组合多个散列值时,可以调用 ObjeCtS.hash 并提供多个参数。这 个方法会对各个参数调用 Objects.hashCode, 并组合这些散列值。这样 Employee.hashCode 方 法可以简单地写为:
public int hashCode(){ return Object.hash(name,salary,hireDay); }
Equals 与 hashCode 的定义必须一致:如果 x.equals(y) 返回 true, 那么 x.hashCode( ) 就必 须与 y.hashCode( ) 具有相同的值。例如, 如果用定义的 Employee.equals 比较雇员的 ID,那 么 hashCode 方法就需要散列 ID,而不是雇员的姓名或存储地址。
toString 方法
toString方法, 它用于返回表示对象值的字符串
public String toString(){ return getClass().getName() "[name=" name ",salary=" salary ",hireDay=" hireDay "]"; }
随处可见 toString方法的主要原因是:只要对象与一个字符串通过操作符“ ” 连接起 来,Java 编译就会自动地调用 toString方法,以便获得这个对象的字符串描述。
Point p = new Point(10,20); String message = "The current position is" p; //automatically invokes p.toString();
Object 类定义了 toString 方法, 用来打印输出对象所属的类名和散列码。例如, 调用 System.out.println(System.out)
将输出下列内容: java.io.PrintStream@2f6684
之所以得到这样的结果是因为 PrintStream 类的设计者没有覆盖 toString方法。
注意:数组要变成字符串---调用静态 方法 Arrays.toString,因为数组继承了 object 类的 toString 方法:
int[] luckyNumbers = {2,3,4,5,6,7}; String s = s luckyNumbers; //生成字符串“ [I@la46e30” 不是想要的结果
【关键:
- 所有的数组类型,不管是对象数组还是基本类型的数组都扩展了 Object 类
- Equals 与 hashCode 的定义必须一致:如果 x.equals(y) 返回 true, 那么 x.hashCode( ) 就必 须与 y.hashCode( ) 具有相同的值。
- Object 类定义了 toString 方法, 用来打印输出对象所属的类名和散列码。
- 强烈建议为自定义的每一个类增加 toString 方法
】
,