目录
Object类是所有Java类继承体系的根,所有java类包括数组都继承自Object类。Object类中共有12个方法,其中一个private的,两个是protected的,9个是public的.常用的方法列表如下:
方法 | 说明 |
Class getClass() | 返回一个对象运行时的类class对象 |
int hashCode() | 返回该对象的hash值 |
boolean equals(Object obj) | 比较两对象是否相等 |
String toString() | 返回该对象的字符串表示 |
Object clone() | 实现对象的复制 |
1、getClass方法
返回一个对象运行时的类class对象。一个类在加载进虚拟机时,会生成一个代表这个类的java.lang.Class对象,通过这个Class对象可以访问这个类在方法区中的各种数据。
Object object = new Object();
//返回当前对象对应类的Class对象
System.out.println(object.getClass());//class java.lang.Object
ObjectCase objectCase1 = new ObjectCase();
System.out.println(objectCase1.getClass());//class com.study.basic.ObjectCase
ObjectCase objectCase2 = new ObjectCase();
System.out.println(objectCase2.getClass());//class com.study.basic.ObjectCase
// 返回的都是ObjectCase的Class对象
System.out.println(objectCase1.getClass()==objectCase2.getClass());//true
System.out.println(objectCase1.getClass().equals(objectCase2.getClass()));//true
}
2、equals方法
equals方法比较的是两个对象是否相等。Object类中的实现如下,默认比较的是两个对象的地址。
public boolean equals(Object obj){
return (this==obj);
}
一些类如Integer、String、Date都重写了equals方法。以比较两个对象的值来判断两个对象是否相等。String类中的equals方法实现如下:先比较是否是同一个对象,若不是同一个对象,再比较值是否相等。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
注意:
- ==对于基本数据类型的变量比较的是他们的值是否相等。对于引用变量比较的是他们的内存地址。equals方法用于比较引用变量,默认实现是调用==比较内存地址,与==返回的结果相同,但对于一些重写了eqauls方法的类而言,equals方法与==方法返回的结果并不保证一致。
- 重写equals方法之后,必须重写hashCode方法,以保证eqauls相等的两个对象的hashCode相等。否则这个类无法和基于hash散列的集合一起正常运作,如HashMap、HashSet和HashTable.
- 重写equals方法必须要遵守equals方法的通用约定,否则依赖这些约定的类如集合类中的list、map等就可能会无法正常运作。(建议重写eqalus方法时仔细参考相关约定)
- 自反性:对于任何非null的引用值x,需满足x.equals(x)返回true
- 对称性:对于任何非null的引用值x、y,需满足x.equals(y)返回true时,y.equals(x)也必须返回true
- 传递性:对于任何非null的引用值x、y、z,满足x.equals(y)返回true且y.equals(z)返回true时,x.equals(z)也必须返回true
- 一致性:对于任何非null的引用值x、y,只要equals比较在对象中所用的信息没有被修改时,那么多次x.equals(y)会一致的返回true或一致的返回false
- 非空性:对于任何非null的引用值x,x.equals(null)必须返回false
参考effectice java 第8条
3、hashCode()方法
hashCode方法返回的是对象的hash值,hash值在不同的JVM中默认实现是不同的,有些是返回的存储地址,但有些返回的是和存储地址相关联的值。
对于hashCode方法方法,使用时需要遵守Object类中对于hashCode方法的约定,javaSE规范中如下:
- 在应用程序的执行期间,只要对象的equals方法的比较操作用到的信息没有被修改,那么对这个对象调用多次,hashCode方法每次都必须返回同一整数。在同一个应用程序的多次执行过程中,每次调用的返回的证书可能不一致
- 如果两个对象根据equals方法比较是相等的,那么这两个对象的hashCode方法返回必须返回同样的整数
- 如果两个对象根据equals方法比较是不相等的,那么这两个对象的hashCode方法不一定要产生同样的整数
static void hashCodeTest(){
Object o1 = new Object();
System.out.println(o1);
System.out.println(o1.hashCode());
System.out.println(Integer.toHexString(o1.hashCode()));
//Integer 类重写了hashCode方法,并且生成的hash值就是Integer对象的基本值
Integer i1 = 300;
Integer i2 =300;
System.out.println(i1.equals(i2));//true
System.out.println(i1.hashCode());//300
System.out.println(i2.hashCode());//300
//String类也重写了hashCode方法,保证两个值相等的对象返回的hashCode值相等
String s1 = "abc";
String s2 = "abc";
System.out.println(s1.equals(s2));//true
System.out.println(s1.hashCode());//96354
System.out.println(s2.hashCode());//96354
}
参考effectice java 第9条
4、toString方法
Object类默认实现的toString方法如下,返回的是类名+@+hash值
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
5、clone方法
clone方法是一个potected方法,表明对对象的克隆。
使用:由于clone方法是protected的,子类需要implements Cloneable接口,重写clone方法并且声明为public,才可被调用。示例:
public class People implements Cloneable{
int a;
ParentClass parentClass;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
......
static void cloneTest(){
People p1 = new People();
p1.a=1;
ParentClass parentClass = new ParentClass(3);
p1.parentClass = parentClass;
try{
People p2 = (People) p1.clone();
System.out.println(p1==p2);//false
System.out.println(p1.equals(p2));//false
System.out.println(p1.a==p2.a);//true
System.out.println(p1.parentClass==p2.parentClass);//true
}catch (Exception e){
}
}
注意:clone方法实现的是浅拷贝(生成一个新的对象,对象中的基本类型字段的值和源对象相同,引用字段与源对象指向的地址相同),若想实现深拷贝需要重写 clone 方法实现域对象的深度遍历式拷贝。
effective java 11条,阿里编程规约->编程规约->OOP 规约20条
6、语法糖:自动装箱和拆箱
基础类型与它们的包装类有如下几种情况时,编译器会自动帮我们进行装箱或拆箱.
- 进行 = 赋值操作(装箱或拆箱)
- 进行+,-,*,/混合运算 (拆箱)
- 进行>,<,==比较运算(拆箱)
- 调用equals进行比较(装箱)
- ArrayList,HashMap等集合类 添加基础类型数据时(装箱)
static void autoBox(){
/**
*
*/
// unbox 等价于 int a= new Integer(200).intValue();
int a = new Integer(200);
// box 等价于Integer b = Integer.valueOf(200);
Integer b = 200;
//auto unbox
System.out.println(a+b);//400
// unbox
System.out.println(a==b);//true
// unbox
System.out.println(b==a);//true
// box
System.out.println(b.equals(a));//true
//box 注:Integer.valueOf方法在-127~127范围内返回的是从缓存中取出的Integer对象,
// 在这个范围之外返回的是新的对象。
Integer aa =100;
Integer bb =100;
System.out.println(aa==bb);//true
Integer aa1 =200;
Integer bb1 =200;
System.out.println(aa1==bb1);//false
}