Java基础(7) Object类

时间:2024-06-10 16:07:18

目录

一、Object类是什么?

1.定义

2.作用

二、Object类的方法之equals()

1.==

2.equals()

3.==和equals的区别

三、Object类的方法之toString()

 四、Object类的方法之clone()

1.定义

2.基本概念

3.使用clone()方法的步骤

4.举例

五、Object类的方法之finalize()

1.概念

2.举例

六、Object类的方法之getClass()

1.概念

2.举例

总结


一、Object类是什么?

1.定义

        类 java.lang.Object是类层次结构的根类,即所有其它类的父类。每个类都使用 Object 作为超类。

2.作用

        Object类型的变量与除Object以外的任意引用数据类型的对象都存在多态引用

method(Object obj){…} //可以接收任何类作为其参数

Person o = new Person();  
method(o);

  • 所有对象(包括数组)都实现这个类的方法。

  • 如果一个类没有特别指定父类,那么默认则继承自Object类。例如:

public class Person {
    ...
}
//等价于:
public class Person extends Object {
    ...
}


二、Object类的方法之equals()

1.==

基本类型比较值:只要两个变量的值相等,即为true。 

int a=10; 
if(a==22){…}

引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,==才返回true。

Person p1=new Person();  	    
Person p2=new Person();
if (p1==p2){…}

用“==”进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错。

2.equals()

所有类都继承了Object,也就获得了equals()方法。还可以重写。

只能比较引用类型,Object类源码中equals()的作用与“==”相同:比较是否指向同一个对象。

  • 格式:obj1.equals(obj2)

  • 特例:当用equals()方法进行比较时,对类File、String、Date及包装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个对象;

    • 原因:在这些类中重写了Object类的equals()方法。

  • 当自定义使用equals()时,可以重写。用于比较两个对象的“内容”是否都相等

  • 重写equals()方法的原则

    • 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。

    • 自反性:x.equals(x)必须返回是“true”。

    • 传递性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。

    • 一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。

    • 任何情况下,x.equals(null),永远返回是“false”;

      x.equals(和x不同类型的对象)永远返回是“false”。

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 重写equals()方法
    @Override
    public boolean equals(Object obj) {
        // 检查是否是同一个对象的引用
        if (this == obj) {
            return true;
        }
        
        // 检查对象是否为空,或者对象是否是不同的类型
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        
        // 将obj转换为Person类型
        Person other = (Person) obj;
        
        // 比较对象内容
        return age == other.age && (name != null ? name.equals(other.name) : other.name == null);
    }

    public static void main(String[] args) {
        Person person1 = new Person("Alice", 25);
        Person person2 = new Person("Alice", 25);
        Person person3 = new Person("Bob", 30);
        
        // 自反性
        System.out.println("Reflexivity: " + person1.equals(person1)); // true
        
        // 对称性
        System.out.println("Symmetry: " + person1.equals(person2)); // true
        System.out.println("Symmetry: " + person2.equals(person1)); // true
        
        // 传递性
        Person person4 = new Person("Alice", 25);
        System.out.println("Transitivity: " + person1.equals(person2)); // true
        System.out.println("Transitivity: " + person2.equals(person4)); // true
        System.out.println("Transitivity: " + person1.equals(person4)); // true
        
        // 一致性
        System.out.println("Consistency: " + person1.equals(person2)); // true
        System.out.println("Consistency: " + person1.equals(person2)); // true
        
        // 比较null
        System.out.println("Null comparison: " + person1.equals(null)); // false
        
        // 比较不同类型
        String str = "some string";
        System.out.println("Different type comparison: " + person1.equals(str)); // false
    }
}

3.==和equals的区别

  • == 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址

  • equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是==;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。

  • 具体要看自定义类里有没有重写Object的equals方法来判断。

  • 通常情况下,重写equals方法,会比较类中的相应属性是否都相等。


三、Object类的方法之toString()

方法签名:public String toString()

① 默认情况下,toString()返回的是“对象的运行时类型 @ 对象的hashCode值的十六进制形式"

② 在进行String与其它类型数据的连接操作时,自动调用toString()方法

Date now=new Date();
System.out.println(“now=”+now);  //相当于
System.out.println(“now=”+now.toString()); 

③ 如果我们直接System.out.println(对象),默认会自动调用这个对象的toString()

因为Java的引用数据类型的变量中存储的实际上时对象的内存地址,但是Java对程序员隐藏内存地址信息,所以不能直接将内存地址显示出来,所以当你打印对象时,JVM帮你调用了对象的toString()。

④ 可以根据需要在用户自定义类型中重写toString()方法 如String 类重写了toString()方法,返回字符串的值。

s1="hello";
System.out.println(s1);//相当于System.out.println(s1.toString());

public class Animal {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Animal{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}

 四、Object类的方法之clone()

1.定义

clone()方法是Java中用于创建对象副本的一种方法。它由Object类定义,并且所有类都继承了它。下面是关于clone()方法的详细讲解:

2.基本概念

  • 浅拷贝: 复制对象时,只复制对象的基本数据类型字段,对于引用类型字段,只复制引用而不复制引用指向的对象。
  • 深拷贝: 复制对象时,不仅复制对象的基本数据类型字段,还复制引用类型字段引用的对象,即复制整个对象图。

3.使用clone()方法的步骤

(1)实现Cloneable接口:

一个类必须实现Cloneable接口,否则调用clone()方法时会CloneNotSupportedException

(2)重写clone()方法:

在类中重写clone()方法,并将其访问修饰符设为public

4.举例

class Person implements Cloneable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 重写clone()方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }

    public static void main(String[] args) {
        try {
            Person person1 = new Person("Alice", 25);
            Person person2 (Person) person1.clone();

            // 输出两个对象
            System.out.println("person1: " + person1);
            System.out.println("person2: " + person2);

            // 比较两个对象是否是同一个引用
            System.out.println("person1 == person2: " + (person1 == person2)); // false
            System.out.println("person1.equals(person2): " + person1.equals(person2)); // true

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}
  • 实现Cloneable接口:

    • class Person implements CloneablePerson类实现了Cloneable接口,表示该类的实例可以被克隆。
  • 重写clone()方法:

    • protected Object clone() throws CloneNotSupportedException:重写clone()方法,并调用super.clone()来实现浅拷贝。
    • super.clone()方法调用父类Objectclone()方法,创建当前对象的副本。
  • 测试代码:

    • 创建person1对象,并通过clone()方法创建person2对象。
    • 输出person1person2的内容。
    • 比较person1person2是否是同一个引用(结果为false,因为是两个不同的对象)。
    • 比较person1person2的内容是否相等(结果为true,因为内容相同)。

五、Object类的方法之finalize()

1.概念

  • 当对象被回收时,系统自动调用该对象的 finalize() 方法。(不是垃圾回收器调用的,是本类对象调用的)

    • 永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。

  • 什么时候被回收:当某个对象没有任何引用时,JVM就认为这个对象是垃圾对象,就会在之后不确定的时间使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用 finalize()方法。

  • 子类可以重写该方法,目的是在对象被清理之前执行必要的清理操作。比如,在方法内断开相关连接资源。

    • 如果重写该方法,让一个新的引用变量重新引用该对象,则会重新激活对象。

  • 在JDK 9中此方法已经被标记为过时的。

2.举例

public class Resource {
    private String resourceName;

    public Resource(String resourceName) {
        this.resourceName = resourceName;
        System.out.println(resourceName + " has been created.");
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            System.out.println(resourceName + " is being finalized.");
            // 在这里执行必要的清理操作,比如关闭资源
        } finally {
            super.finalize();
        }
    }

    public static void main(String[] args) {
        Resource res = new Resource("MyResource");

        // 将res置为null,使对象成为垃圾对象
        res = null;

        // 手动调用垃圾回收器
        System.gc();

        // 等待一段时间以确保垃圾回收器有机会运行
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("End of main method");
    }
}
  • Resource类:

    • resourceName:资源的名称。
    • Resource(String resourceName):构造函数,创建资源对象时输出信息。
    • finalize():重写的finalize()方法,在对象被回收之前执行清理操作。
  • main方法:

    • 创建一个Resource对象res
    • res设置为null,使其成为垃圾对象。
    • 调用System.gc(),请求JVM进行垃圾回收(注意,这只是请求,JVM可能不会立即执行垃圾回收)。
    • 使用Thread.sleep(1000)等待一段时间,以确保垃圾回收器有机会运行。
    • 打印"End of main method"。

六、Object类的方法之getClass()

1.概念

public final Class<?> getClass():获取对象的运行时类型

因为Java有多态现象,所以一个引用数据类型的变量的编译时类型与运行时类型可能不一致,因此如果需要查看这个变量实际指向的对象的类型,需要用getClass()方法

2.举例

package com.example;

public class Person {
    // 省略类定义
}

public class Main {
    public static void main(String[] args) {
        Object obj = new Person();
        System.out.println(obj.getClass()); // 运行时类型
    }
}

运行结果:class com.example.Person


总结

        本篇对Java的Object类进行了详细介绍,其中也对几个重要方法进行了讲解。部分内容源自网络,如有侵权请联系作者删除,谢谢!