学生类:
public class Student implements Cloneable{
    private String name;
    private int age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }


    @Override
    public boolean equals(Object o) {
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
----------------------------------------------------

public class objectDemon1 {
    public static void main(String[] args) throws CloneNotSupportedException {
       /*
        public String toString()//返回对象的字符串表示形式
        public boolean equals(Object obj)//比较两个对象是否相等
        public Object clone()//对象克隆

        */
        //1.toString 返回对象的字符串表示形式
        Object o=new Object();
        String str1=o.toString();
        System.out.println(str1);//java.lang.Object@1b6d3586
        //sout的核心逻辑:
        //当我们打印一个对象时,会自动调用对象的toString方法,把对象变成字符串
        //所以就会默认打印地址值
        System.out.println(o);//java.lang.Object@1b6d3586
        //处理方案:重写toString方法
        Student s=new Student("zhangsan",18);
        System.out.println(s);//Student{name = zhangsan, age = 18}


        //2.equals 比较两个对象是否相等
        //默认比较的是地址值
        Object o1=new Object();
        Object o2=new Object();
        System.out.println(o1.equals(o2));//false
        //处理方案:重写equals方法
        Student s1=new Student("zhangsan",18);
        Student s2=new Student("zhangsan",18);
        System.out.println(s1.equals(s2));//true

        //equals方法易错点:
        String str="abc";
        StringBuilder sb=new StringBuilder("abc");
        System.out.println(str.equals(sb));//false
        System.out.println(sb.equals(str));//false
        //第一个调用的是String类的equals方法,如果参数是字符串,就比较内容,不是就直接返回false
        //第二个调用的是StringBuilder类的equals方法,StringBuilder没有重写equals方法,所以使用的是Object类的equals方法,比较的是地址值
        System.out.println(sb.toString().equals(str));//true
        //这里StringBuilder类的toString()方法会返回一个新的 String对象,String类重写了Object类的equals方法,所以比较的是内容


        //3.clone 对象克隆
        //Object类的clone方法是一个受保护的方法,不能直接调用,需要重写clone方法,并且需要实现Cloneable接口
        Student s3=new Student("zhangsan",18);
        Student s4= (Student) s3.clone();//克隆出来的是一个object对象,要强转成Student对象
        System.out.println(s3);//Student{name = zhangsan, age = 18}
        System.out.println(s4);//Student{name = zhangsan, age = 18}
        //object中的克隆是浅克隆
        System.out.println(s3==s4);//false

        //objects
        Student s5=new Student("zhangsan",18);
        Student s6=null;
       boolean flag= Objects.equals(s5,s6);
        System.out.println(flag);//false
        //Objects中的equals方法会判断对象是否为空,如果为空,就返回false,如果不为空,就调用对象的equals方法
        //Objects中的equals方法是一个静态方法,可以直接调用,不需要创建对象

        //判断对象是否为空
        Objects.isNull(s5);//false
        Objects.isNull(s6);//true



   }
}