Skip to content

Object 类

toString

默认实现

java
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
  • getClass().getName():返回对象的类名(包括包名)。
  • hashCode():返回对象的哈希值(整数)。
  • Integer.toHexString(hashCode()):把哈希值转成十六进制。
  • 默认输出示例:
java
com.example.MyClass@1a2b3c4

重写

为了打印更有意义的信息,通常会在自定义类中重写 toString()

java
class Person {
    String name;
    int age;

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

打印对象时System.out.println(obj) 会自动调用 obj.toString()

java
Person p = new Person();
p.name = "Alice";
p.age = 25;
System.out.println(p); // 自动调用 toString()
java
Person{name='Alice', age=25}

equals

用来判断两个对象是否“相等”

默认实现

java
public boolean equals(Object obj) {
    return (this == obj);
}

默认实现其实就是用 == 判断是否是同一个对象引用

java
String a = new String("hello");
String b = new String("hello");

System.out.println(a == b);       // false,引用不同
System.out.println(a.equals(b));  // false,默认 Object 的 equals 也是引用比较

字符串只能使用equals比较是否相等,String已重写了equals方法

重写

默认的 equals() 只比较引用,对于我们自定义的类,大多数时候我们想比较对象的 内容/属性 是否相等,而不是引用。

java
package org.example.boot.bean;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Date {
    private int year;
    private int month;
    private int day;

    @Override
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (this == obj) return true;
        if (obj instanceof Date) {
            Date date = (Date) obj;
            if (this.year == date.year && this.month == date.month && this.day == date.day) {
                return true;
            }

        }
        return false;
    }
}

clone

clone() 是 Object 类中的一个方法,用于复制当前对象,生成一个新的对象。它属于 Java 提供的一种对象拷贝机制。

默认实现

Object 类中的定义:

java
protected native Object clone() throws CloneNotSupportedException;
  • protected:默认只能在本类或子类中使用

  • native:底层由 JVM实现

  • 返回值:Object

  • 可能抛出 CloneNotSupportedException

Object的clone为什么不设计成public?

Java 不希望所有对象默认都可以被克隆。任何对象都可以随意复制,这会带来很多问题。因此设置为protected将控制权交给类作者决定对象是否可以被克隆

浅拷贝

如果一个类想要使用 clone(),必须:

  1. 实现 Cloneable 接口
  2. 重写 clone() 方法,并提高访问权限(原有权限是protected,一般改为 public)

Cloneable 是一个 标记接口,没有方法,只是告诉 JVM:这个类允许被 clone。如果不实现 Cloneable,调用 clone() 会抛异常。

java
class Person implements Cloneable {

    String name;
    int age;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
java
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {

        Person p1 = new Person();
        p1.name = "Tom";
        p1.age = 20;

        Person p2 = (Person) p1.clone();

        System.out.println(p1 == p2); // false
        System.out.println(p1.name);  // Tom
        System.out.println(p2.name);  // Tom
    }
}

深拷贝

clone() 默认是 浅拷贝,深拷贝需要 手动 clone 引用对象

java
package org.example.boot.bean;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Address implements Cloneable{
    private String city;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
java
package org.example.boot.bean;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Person implements Cloneable{
    private String name;
    private int age;
    private Address address;


    @Override
    public Object clone() throws CloneNotSupportedException {
        Person person = (Person) super.clone();
        person.address = (Address) address.clone();
        return person;
    }
}
java
import lombok.val;
import org.example.boot.bean.Address;
import org.example.boot.bean.Person;
import org.junit.jupiter.api.Test;

public class PersonTest {
    @Test
    void test1() throws CloneNotSupportedException {
        Address address = new Address("上海");
        Person p1 = new Person("lai",18, address);
        System.out.println(p1);
        Person p2 = (Person) p1.clone();
        address.setCity("三明");
        System.out.println(p1);
        System.out.println(p2);
    }
}

缺陷

企业中 不推荐使用 clone,原因:

  1. Cloneable 设计不好(标记接口)
  2. clone() 返回 Object 需要强转
  3. 容易出现 浅拷贝问题
  4. 需要处理异常

通常使用BeanUtils:

java
BeanUtils.copyProperties(p1, p2);

hashCode

java
public native int hashCode();

默认 hashCode ≈ 对象的“内存标识”

同一个对象,多次调用 hashCode 的结果是一样的,因为引用没有发生变化