【Java】Object类详解(equals hashCode toString)

目录

  • (一)Object类是啥
  • (二)equals方法
    • (1)原理
    • (2)总结
    • (3)equals方法特性
  • (三)hashCode方法
  • (三)toString方法

(一)Object类是啥

Object类是所有类的始祖,在java中每个类都是由它扩展得到的,但是并不需要这样写

public class Employee extdens Object

在新建一个类时我们可以看到

【Java】Object类详解(equals hashCode toString)_第1张图片

如果没有明确地指出超类,Object就会被认为是这个类的超类,可以使用Object类型的变量引用任何类型的对象:

Object obj = new Employee("小明",2000);

Object类型的变量只能用于作为各种值的通用持有者,想要对其进行具体操作,还需要知道对象的原始数据类型,并进行相应的类型转换:

Employee e = (Employee)obj;

在java中,只有基本类型不是对象,例如数值,字符,布尔类型。而所有的数组类型,对象数组,基本类型数组都扩展了Object类:

Employee[] staff = new Employee[10];
obj = staff
obj = new int[10];

(二)equals方法

(1)原理

Object类中的equals方法用于检测一个对象是否等于另外一个对象。在Object类中,这个方法将判断俩个对象是否具有相同的引用,如果俩个对象具有相同的引用,他们一定是相等的。下面是Object类中equals方法源码:

 * @param   obj   the reference object with which to compare.
         * @return  {@code true} if this object is the same as the obj
         *          argument; {@code false} otherwise.
         * @see     #hashCode()
         * @see     java.util.HashMap
         */
        public boolean equals(Object obj) {
            return (this == obj);
        }

Object类里的equals方法直接判断equals对象与obj所引用的对象是否相同,来一波操作(这里的equals方法已被String类重写了),看看equals方法与“ == ”运算符的区别:

int n=1,m=1;
String a = new String("小明");
String b = new String("小明");

String c = "小马";
String d = "小马";

System.out.println(n==m);		//true
System.out.println(n.equals(m));//错误

System.out.println(a==b);		//false
System.out.println(a.equals(b));//true

System.out.println(c==d);		//true
System.out.println(c.equals(d))	//true

n与m的比较可知,equals不能用于基本类型,为什么a,b的比较结果和c,d的比较结果不一样?我们来看一下java内存划分:
【Java】Object类详解(equals hashCode toString)_第2张图片
栈区:每调用一个方法会创建一个栈帧,存放局部变量,堆区:存放new出来的对象,此对象由垃圾收集器收集。还有个方法区包含类的所有信息。

//n与m比较的是值
System.out.println(n==m);		//true
System.out.println(n.equals(m));//错误

//a与b的地址不一样
System.out.println(a==b);		//false
//a与b的对象引用一样
System.out.println(a.equals(b));//true

//c与d的地址相同
System.out.println(c==d);		//true
//c与d的地址相同
System.out.println(c.equals(d))	//true

(2)总结

  • ==运算符
    1.如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等。
    2.如果作用于引用类型的变量,则比较的是所指向的对象的地址。
  • equals
    1.equals方法不能作用于基本数据类型的变量。
    2.如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象。
    3.诸如String,Data等类对equals方法进行了重写的话,比较的是所指向的对象的内容

(3)equals方法特性

  1. 自反性:对于任何非空引用x,x.equals(x)应该返回true;
  2. 对称性:对于任何引用x,和y,当且仅当,y.equals(x)返回true,x.equals(y)也应该返回true;
  3. 传递性:对于任何引用x,y,z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true;
  4. 一致性:如果x,y引用的对象没有发生变化,反复调用x.equals(y)应该返回同样的结果;
  5. 对于任意非空引用x,x.equals(null)返回false;

(三)hashCode方法

散列码是由对象导出的一个整型数值,散列码是没有规律的,如果a和b是不同的两个对象,那么a.hashCode()和b.hashCode()基本不会相同。下面是String类使用的hashCode方法:

int hash=0;
for(int i=0; i<length ;i++)
	hash =31*hash+charAt(i);

hashCode方法定义在Object类中,因此每个对象都有一个默认的散列码,其值为对象的储存地址,看个例子:

String s = "OK";
StringBuilder sa = new StringBuilder(s);
System.out.println(s.hashCode()+" "sa.hashCode);
String t = new String("OK");
StringBuilder ta = new StringBuilder(t);
System.out.println(s.hashCode()+" "sa.hashCode);

输出:2556 20526976
      2556 20527411
s与t是String类的对象,散列码由字符串的内容导出的,所以相同。而sa与ta的散列码不同,是因为StringBuilder类里没有定义hashCode()方法,其散列码由Object类默认hashCode()方法导出的对象地址。
如果重新定义equals方法,就必须重新定义hashCode方法,以便用户将对象插入到散列表中。还有如果x.equals(y)返回true,那么x.hashCode()就必须和y.hashCode具有相同的值,反过来,如果x和y的散列码一样,x.equals(y)不一定返回true.


(三)toString方法

也是Object类里比较重要的类,用于返回对象值的字符串,绝大部分类的 toString 类遵循这样的格式:类的名字,随后就是一对方括号括起来的预值。

public String toString(){
	return "Student[name="+name+"]";
	}

如果x是任意对象,直接打印x,println方法会自动调用x.toString方法得到字符串。

Student x = new Student("小明");
System.out.println("x")
//输出
//Student[小明]

数组也继承了Object类的toString方法,在调用x.toString()的地方可以用 “”+x 替代,这里的x就是x.toString()

int[] a ={1,2,3};
String s = ""+a;
String s = Arrays.toString(a);
//将生成字符串 [1,2,3] 

你可能感兴趣的:(java)