初识Object
位于Java.lang.Object 中,编译时会自动导入:
(1)超类,所有类都直接或间接地继承这个类;
(2)所有对象(包括数组)都实现这个类的方法;
(3)Object 类型的变量,可以装载任何类型的对象。
Object方法(共11种)
简单介绍常用的5个方法
(1) public String toString()
return getClass().getName() + “@” + Integer.toHexString(hashCode());
默认返回的是一个类名@对象的hashcode值的十六进制(0~ffffff)
将一个对象转成一个字符串,建议所有子类重写该方法
特别说明:
当我们打印一个对象==>System.out.println(Object)的时候,JVM会自动调用这个对象的toString()方法
(2)public final native Class<?> getClass();
==>返回的是Object的运行时类
**(3)protected void finalize() **
在实际中,不是程序员调用,而是JVM帮我们自动调用
这个方法一般在该对象被GC回收之前一刻调用==>临终遗言
如果你的类不是系统类型,不需要重写,像FileInputStream等和操作系统底层资源有关系的类型才需要重写,为什么呢?
因为系统资源往往是和操作系统底层的东西有关,而底层,大多是用C/C++实现,C/C++对象的回收,就需要我们手动回收
特别说明:
每一个对象的finalize()只会调用一次,若在finalize()中,有某句代码,使得当前对象被重新引用,会使得这个对象复活
那么等他再次成为垃圾的时候就会直接被回收,不会再调用这个方法。
面试题final.finalize,finally的区别
finalize()是对象被确认为垃圾(不再有对该对象的引用时),由垃圾回收器去调用,每个对象调用一次
(4)public int hashCode()
返回对象的哈希码值
==》每个对象都会有一个数字代表这个对象,理想状态下是一个对象对应一个哈希值
支持这种方法是为了散列表,如HashMap提供的那样 。
规定:
A:如果一个对象的内容没用改变。在执行Java应用程序时,多次在同一个对象上调用该方法, hashCode方法必须始终返回相同的整数,前提是修改了对象中equals比较中的信息。
B:如果equals(Object)方法两个对象相等,则在调用hashCode方法必须产生相同的整数结果。
C:如果两个对象equals(Object)不相等,那么调用hashCode方法产生不同的整数结果,也可能相同。
equals(Object)不等,hashCode相等的特例如下:
System.out.println("Aa".hashCode());//2112
System.out.println("BB".hashCode());//2112
(但是,程序员应该意识到,为不等对象生成不同的整数结果会提高哈希表的性能。 )
(5)public boolean equals(Object obj)
- 1:建议子类重写是,要一起将hashCode也重写,保证equals()方法两个对象相等,则在调用hashCode方法必须产生相同的整数结果
- 2:重写遵循原则:
自反性: x.equals(x) 为true
对称的 :x.equals(y) 为true,则y.equals(x) 为true(对于任何非空引用值x和y )
传递性 :x.equals(y) 为true,y.equals(z) 为true,则z.equals(x) 为true(对于任何非空引用值x和y,z )
一致性 :对于任何非空引用值x和y ,多次调用x.equals(y)始终返回true或始终返回false ,没有设置中使用的信息equals比较上的对象被修改。
对于任何非空的参考值x , x.equals(null)应该返回false 。
例子:
public static class Student {
private String name;
private int id;
public Student(String name, int id) {
super();
this.name = name;
this.id = id;
}
public Student() {
super();
}
@Override
public String toString() {
return "Student [name=" + name + ", id=" + id + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
//result = prime * result + getEnclosingInstance().hashCode();
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
/*
* s1.equals(s2)
* this ->s1
* obj ->s2
*/
@Override
public boolean equals(Object obj) {
if (this == obj)//地址相同,直接返回
return true;
if (obj == null) //既然能进入到该方法,则表明s1必定不为空,否则会报空指针异常
//当obj==null,则两者内容必然不相等
return false;
/*
* 既然能进入到该方法,则表明s1必然为student类型,而obj可能不是Student类型,因此要获取obj的运行时类型
*/
if (getClass() != obj.getClass())
return false;
//obj向下转型,否则,obj为Object类型,无法访问到Student的成员变量id,name
//不需要instanceof来判断obj类型,因为,如obj不是Student,上一个判断已经返回false
Student other = (Student) obj;
if (id != other.id)
return false;
if (name == null) {//this.name ==null
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
/*
* 不可以if(name == other.name)
* 因为这样就就比较的是对象的地址,而不是内容,
* if(name.equals(other.name))
* 这样的话,如果name为空,就会报空指针异常
* equals()的调用者要确保是不为空的。
*/
return true;
}
}