常用类解析:Object类
- 前言
- 一、Object类
- 1.什么是Object类 ?
- 2.具体方法的详细讲解
前言
一、Object类
1.什么是Object类 ?
Object类是所有类的最终父类,就算某一个类的父类没有声明为Object那它的最终的祖先肯定是Object。
Object类源码就在所下载的jdk的包下面,有src压缩包,里面有Object类的源码,就在oracle网站下载的API的当中 java.lang这个包下面,里面有很多定义好的方法:
然后就得到了Object类的源码,里面有一段英文的文档注释:
就相当于是API里面的文档注释,就是类似是说明书,就是直接翻译过来的:
具体的方法如下:
2.具体方法的详细讲解
(1) getClass()
public final native Class<?> getClass();
//相当于获取对象最本质的数据类型
我们可以根据实例来理解:
public class ObjectDemo {
public static void main(String[] args) {
String s = "abc";
System.out.println(s.getClass());
//多态
Animal a1 = new Dog();
Animal a2 = new Cat();
System.out.println(a1.getClass());
System.out.println(a2.getClass());
}
}
//多态
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
验证s,a1,a2对象所调用的类:
![在这里插入图片描述](https://img-blog.csdnimg.cn/57e64bb19a304be787d967928d0a73bd.png)
(2)hashCode()
```java
public native int hashCode();
//返回对象的哈希码的值,如果该类没有重写hashCode的
//hashCode默认值就是对象在堆内存中的真实物理地址
我们可以根据实例来理解(在没有重写方法前,调用的是Object类里面的hascode()的方法,默认值就是对象在堆内存中的真实物理地址):
public class ObjectDemo {
public static void main(String[] args) {
//多态
Animal a1 = new Dog();
Animal a2 = new Cat();
System.out.println(a1.hashCode());
System.out.println(a2.hashCode());
}
}
//多态
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
结果:显示的是a1和a2的真实物理地址
若对hascode()方法进行重写就会返回重写的值,直接覆盖了默认值:
public class ObjectDemo {
public static void main(String[] args) {
//多态
Animal a1 = new Dog();
Animal a2 = new Cat();
System.out.println(a1.hashCode());
System.out.println(a2.hashCode());
}
}
//多态
class Animal {
//重写了hascode()方法
@Override
public int hashCode() {
return 100;
}
}
class Dog extends Animal {}
class Cat extends Animal {}
结果:显示的是a1和a2的重写后的值
(3)equals(Object obj)
public boolean equals(Object obj) {
return (this == obj);
}
//Object本身equals比的是自身对象this和传入对象obj的地址值
//如需重新定义等于,则子类重写,按需比较即可
注意这里的equals方法里面返回的是this==obj,也就是说如果传入的不是自己本身,就永远是返回false,注意这里的 两边永远比的是对象的真实物理内存地址!
public class ObjectDemo {
public static void main(String[] args) {
//多态
Animal a1 = new Dog();
Animal a2 = new Cat();
System.out.println(a1.hashCode());
System.out.println(a2.hashCode());
System.out.println(a1 == a2);
//== 两边永远比的是对象的真实物理内存地址!
System.out.println(a1.equals(a2));
}
}
//多态
class Animal {}
class Dog extends Animal {}
结果:a1与a2的真实物理地址不同,返回的是false,equals()方法没有传入自己也是返回false:
如果对equals(Object obj)方法进行重写,就会改变结果,根据自己所需要比较的内容来比是否相等:
public class ObjectDemo {
public static void main(String[] args) {
Person p1 = new Person("小明",21);
Person p2 = new Person("小明",21);
System.out.println(p1);
System.out.println(p2);
System.out.println(p1.equals(p2));
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//重写equals(Object obj)方法
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() == obj.getClass()) {
Person other = (Person) obj;
return this.name.equals(other.name) && this.age == other.age;
} else {
return false;
}
}
}
结果:重写后的equals(Object obj)方法,会根据所写的要求来执行,不会默认执行比较真实物理地址的值:
(4)toString()
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
//Object本身的toString返回的是对象最本质的数据类型的名称+"@"+哈希值的十六进制形式
//如需重新定义对象的字符串形式,则子类重写,按需拼接数据即可
注意,打印对象本身就是相当于打印它们的toString()方法;
public class ObjectDemo {
public static void main(String[] args) {
//多态
Animal a1 = new Dog();
Animal a2 = new Cat();
System.out.println(a1.hashCode());
System.out.println(a2.hashCode());
System.out.println(a1);
System.out.println(a2);
System.out.println(a1 == a2);
//无论hashCode是否重写 == 两边永远比的是对象的真实物理内存地址!
System.out.println(a1.equals(a2));
}
}
//多态
class Animal {
@Override
public int hashCode() {
return 100;
}
}
class Dog extends Animal {}
class Cat extends Animal {}
结果,打印a1和a2,就是相当于打印它们的toString()方法,hashCode重写,100的十六进制是64
如果重写toString()方法,会根据自己所需所写,改变了原本的打印方式:
public class ObjectDemo {
public static void main(String[] args) {
Person p1 = new Person("小明",21);
Person p2 = new Person("小李",11);
System.out.println(p1);
System.out.println(p2);
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//重写toString()方法
@Override
public String toString() {
return name + ":" + age;
}
}
结果:将toString()方法改写成只打印名字和年龄
(5)clone()
protected native Object clone()
//对象的拷贝,对于任何对象 x
创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。这样做的目的是,对于任何对象 x:
- 表达式: x.clone() != x为 true。【保证肯定有新对象创建】
- 表达式: x.clone().getClass() == x.getClass()也为 true,但这些并非必须要满足的要求。【保证对象和副本之间的数据类型是一致的】
- 一般情况下: x.clone().equals(x)为 true,但这并非必须要满足的要求。 【保证对象和副本之间的数据内容是一致的】
因为clone()方法的权限是protected,当不在一个包下且不在一个类下面是无法访问到的,必须得重写clone()的方法,也要实现接口 Cloneable,得让此类有接口 Cloneable的功能可以进行复制的方法。
Object 类的 clone 方法执行特定的复制操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。注意,所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我复制。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。
Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。
返回: 此实例的一个副本。
抛出: CloneNotSupportedException - 如果对象的类不支持 Cloneable 接口,则重写 clone方法的子类也会抛出此异常,以指示无法复制某个实例。
public class ObjectDemo {
public static void main(String[] args) {
Person p3 = new Person("小刘",30);
Person p4 = null;
try {
p4 = (Person) p3.clone();//p3的副本
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(p3);
System.out.println(p4);
System.out.println(p3 == p4);//p3和p4确实是两个对象
System.out.println(p3.equals(p4));//p3和p4确实内容相等
p3.name = "刘小刚";
p3.age = 10;
System.out.println(p3);
}
}
class Person implements Cloneable{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//重写clone()方法
@Override
//要将权限protected改成public
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
//重写toString()方法
@Override
public String toString() {
return name + ":" + age;
}
//重写equals(Object obj)方法
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() == obj.getClass()) {
Person other = (Person) obj;
return this.name.equals(other.name) && this.age == other.age;
} else {
return false;
}
}
}
结果:p4就是p3拷贝的一个新对象,p3的一个副本,内容一致,但是真实物理地址不一致,p3改变了内容,p4也不会改变,两个是两个对象,p4只是原p3的一个拷贝。