所有类的父类 Java Object
Java Object
- 一、什么是Java Object
- 二、Object类的方法
- 1、创建并返回一个对象的拷贝protected Object clone()
- 2、比较两个对象是否相等 boolean equals(Object obj)
- 3、当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此finalize() 方法。
- 4、获取对象的运行时对象的类 Class<?> getClass()
- 5、获取对象的 hash 值 int hashCode()
- 6、唤醒在该对象上等待的某个线程void notify()
一、什么是Java Object
Java Object 类是所有类的父类,也就是说 Java 的所有类都继承了 Object,子类可以使用 Object 的所有方法。(得了,就是Object就是所有类的爸爸)
Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。
Object 类可以显示继承,也可以隐式继承,以下两种方式时一样的:
显示继承:
public class Test extends Object{}
隐式继承:
public class Test{}
下面我们来分析一下Object的源码:
package java.lang;public class Object { private static native void registerNatives(); static { registerNatives(); } //获取对象的运行时对象的类 public final native Class<?> getClass(); //获取对象的 hash 值 public native int hashCode(); //比较两个对象是否相等 public boolean equals(Object obj) { return (this == obj); } //创建并返回一个对象的拷贝 //clone 方法是浅拷贝,对象内属性引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存,相对应的深拷贝则会连引用的对象也重新创建。 //浅克隆复制出来的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。也就是说,克隆之后的对象和之前的对象仍存在一些关联,克隆程度不高,因此也被称为浅克隆。//而深克隆复制出来的所有变量都含有与原来的对象相同的值,那些引用其他对象的变量将指向复制出来的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。 protected native Object clone() throws CloneNotSupportedException; //返回对象的字符串表示形式 public String toString() { return getClass().getName() "@" Integer.toHexString(hashCode()); } //唤醒在该对象上等待的某个线程 public final native void notify(); public final native void wait(long timeout) throws InterruptedException; public final void wait(long timeout, int nanos) throws InterruptedException { if (timeout < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos > 0) { timeout ; } wait(timeout); } public final void wait() throws InterruptedException { wait(0); } //当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此方法。 protected void finalize() throws Throwable { }}
二、Object类的方法
1、创建并返回一个对象的拷贝protected Object clone()
** * @Description: $ clone()案例 * @Author: dyq * @Date: $2021年2月4日 */public class CloneTest implements Cloneable { // 声明变量 String name; int age; public static void main(String[] args) { // 创建对象 CloneTest obj1 = new CloneTest(); // 初始化变量 obj1.name = "科隆"; obj1.age = 20; // 打印输出 System.out.println(obj1.name); // 科隆 System.out.println(obj1.age); //20 try { // 创建 obj1 的拷贝 CloneTest obj2 = (CloneTest) obj1.clone(); // 使用 obj2 输出变量 System.out.println("clone后:"); System.out.println(obj2.name); // 科隆 System.out.println(obj2.age); //20 } catch (Exception e) { System.out.println(e); } }}
结果输出:
科隆20clone后:科隆20
clone 方法是浅拷贝,对象内属性引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存,相对应的深拷贝则会连引用的对象也重新创建。
那么浅克隆跟深克隆有什么区别?
浅克隆复制出来的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。也就是说,克隆之后的对象和之前的对象仍存在一些关联,克隆程度不高,因此也被称为浅克隆。
而深克隆复制出来的所有变量都含有与原来的对象相同的值,那些引用其他对象的变量将指向复制出来的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
2、比较两个对象是否相等 boolean equals(Object obj)
Object equals() 方法用于比较两个对象是否相等。
equals() 方法比较两个对象,是判断两个对象引用指向的是同一个对象,即比较 2 个对象的内存地址是否相等。
注意:如果子类重写了 equals() 方法,就需要重写 hashCode() 方法,比如 String 类就重写了 equals() 方法,同时也重写了 hashCode() 方法。
该方法返回值为布尔型,则如果两个对象相等返回 true,否则返回 false。
案例:
/** * @Description: equals()案例$ * @Author: dyq * @Date: 2021年2月4日$ */public class equalsTest { public static void main(String[] args) { // Object 类使用 equals() 方法 // 创建两个对象 Object obj1 = new Object(); Object obj2 = new Object(); // 判断 obj1 与 obj2 是否相等 // 不同对象,内存地址不同,不相等,返回 false System.out.println(obj1.equals(obj2)); // false // obj1 赋值给 obj3 // String 重写了 equals() 方法 // 对象引用,内存地址相同,相等,返回 true Object obj3 = obj1; System.out.println(obj1.equals(obj3)); // true // String 类使用 equals() 方法 // 创建两个对象 String obj4 = new String(); String obj5 = new String(); // 判断 obj4 与 obj5 是否相等 // 初始化的两个对象都为 null,所以是相等,返回 true System.out.println(obj4.equals(obj5)); // true // 给对象赋值 obj4 = "哥哥"; obj5 = "哥"; // 判断 obj4 与 obj5 是否相等 // 两个值不同,内存地址也不同,所以不相等,返回 false System.out.println(obj4.equals(obj5)); // false }}
结果:
falsetruetruefalse
3、当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此finalize() 方法。
Object finalize() 方法用于实例被垃圾回收器回收的时触发的操作。
在GC准备释放对象所占用的内存空间之前,它将首先调用finalize()方法
finalize()方法中一般用于释放非Java 资源(如打开的文件资源、数据库连接等),或是调用非Java方法(native方法)时分配的内存。
4、获取对象的运行时对象的类 Class<?> getClass()
Object getClass() 方法用于获取对象的运行时对象的类。
示例:
/** * @Description: $getClass * @Author: dyq * @Date: $ */public class getClassTest { public static void main(String[] args) { // getClass() with Object Object obj1 = new Object(); System.out.println("obj1 的类为: " obj1.getClass()); // getClass() with String String obj2 = new String(); System.out.println("obj2 的类为: " obj2.getClass()); // getClass() with ArrayList ArrayList<Integer> obj3 = new ArrayList<>(); System.out.println("obj3 的类为: " obj3.getClass()); // 创建 getClassTest 类的对象 getClassTest classTest = new getClassTest(); // getClassTest 继承 Object 类,Object 是所有类的超类 // 调用 getClass() 方法 System.out.println("classTest的类为:" classTest.getClass()); }}
结果:
obj1 的类为: class java.lang.Objectobj2 的类为: class java.lang.Stringobj3 的类为: class java.util.ArrayListclassTest的类为:class com.Colltion.Test.getClassTest
5、获取对象的 hash 值 int hashCode()
返回对象是哈希值,是一个整数,表示在哈希表中的位置。
示例:
import java.util.ArrayList;/** * @Description: $hashCode() * @Author: dyq * @Date: $ */public class hashCodeTest { public static void main(String[] args) { // Object 使用 hashCode() Object obj = new Object(); System.out.println(obj.hashCode()); //String 和 ArrayList 类都继承了 Object,所以可以直接使用 hashCode() 方法: // String 使用 hashCode() String str = new String(); System.out.println(str.hashCode()); // 0 // ArrayList 使用 hashCode() ArrayList<Integer> list = new ArrayList<>(); System.out.println(list.hashCode()); // 1 //如果两个对象相等,则它们的哈希值也是相等的 // Object 使用 hashCode() Object obj1 = new Object(); // obj1 赋值给 obj2 Object obj2 = obj1; // 判断两个对象是否相等 System.out.println(obj1.equals(obj2)); // true // 获取 obj1 与 obj2 的哈希值 System.out.println(obj1.hashCode()); // 1163157884 System.out.println(obj2.hashCode()); // 1163157884 }}
结果:
46014195801true11631578841163157884
6、唤醒在该对象上等待的某个线程void notify()
notify() 方法只能被作为此对象监视器的所有者的线程来调用。
一个线程要想成为对象监视器的所有者,可以使用以下 3 种方法:
- 执行对象的同步实例方法
- 使用 synchronized 内置锁
- 对于 Class 类型的对象,执行同步静态方法
一次只能有一个线程拥有对象的监视器。
如果当前线程不是此对象监视器的所有者的话会抛出 IllegalMonitorStateException 异常。