Object类讲解

目录

==和equals的对比

equals方法

String类的equals的源码分析

Object类的equals的源码分析

Integer类的equals的源码分析

equals例题

第一题

第二题

hashCode方法

toString方法

基本介绍

finalize方法


==和equals的对比

1.==:既可以判断基本类型,又可以判断引用类型

2.==:如果判断基本类型,判断的是值是否相等。示例:inti=10;double d=10.0;

3.==:如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象

equals方法

4.equals:是Object类中的方法,只能判断引用类型,

5.默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。比Integer,String

代码演示:

package idea.object_;

/**
 * 演示equals方法和==
 */
public class equals01 {
    public static void main(String[] args) {
        A a = new A();
        //==和equals的对比
        //1.==:既可以判断基本类型,又可以判断引用类型
        //2.==:如果判断基本类型,判断的是值是否相等。示例:inti=10;double d=10.0;
        //3.==:如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象

        //比如
        int i = 10;
        double d = 10.0;
        //判断基本数类型
        System.out.println(i == d);//因为int 和 double 都是基本数据类型,所以判断的是值是否相等,因此返回true
        //判断引用类型
        A b = a;
        A c = b;
        //因为把a赋值给了 b 因此b也指向a所指向的空间,因此返回true
        System.out.println(a == c);
        //因为把a赋值给了 c 因此c也指向a所指向的空间,因此返回true
        System.out.println(b == c);

        B bObj = a;
        //因为把a赋值给了 bObj 因此bObj也指向a所指向的空间,因此返回true,即使bObj的编译类型是B,但是指向的还是a所指向的空间,所以返回true
        System.out.println(bObj == a);


        //equals方法
        //4.equals:是Object类中的方法,只能判断引用类型,如何看Jdk源码,看老师演示
        //5.默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。比Integer,String

        //equals 方法,源码怎么查看.
        //把光标放在equals方法,直接输入ctrl+b
        //如果你使用不了. 自己配置. 即可使用.

        /*
        //看看Jdk的源码 String类的 equals方法
        //String类把Object的equals方法重写了,变成了比较两个字符串值是否相同
        public boolean equals(Object anObject) {
        if (this == anObject) {//判断,如果当前对象和传入进来的是同一个对象
            return true;//返回true
        }
        if (anObject instanceof String) {//判断你传入进来的数据类型的运行类型,是不是String类型或者是String类的子类型型
            String anotherString = (String)anObject;//如果是String类型或者是String类的子类型,那么就向下转型
            int n = value.length;
            if (n == anotherString.value.length) {//如果长度相同
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {//然后一个一个的比较字符
                    if (v1[i] != v2[i])//如果发现两个数组中,有一个字符不相同那么就返回false
                        return false;
                    i++;
                }
                return true;//如果两个字符串的所有字符都相等,则返回true
            }
        }
        return false;//如果比较的不是字符串(也就是传入的数据类型,不是String类型或者不是String类型的子类型),则直接返回false
    }
         */

        //String
        //因为String类重写了Object的equals方法,因此判断的是内容是否相同,因此返回false
        System.out.println("hello".equals("abc"));


        //Object
        //看看Object类的 equals()方法是怎么样的
        /*
         Object 的equals 方法默认就是比较对象地址是否相同
         也就是判断两个对象是不是同一个对象.
         public boolean equals(Object obj) {
            return (this == obj);//直接判断当前对象和我们传入的对象是否相同,因为==在判断引用类型的时候,判断的是地址是否相同
        }
         */

        //Integer
        /*
        //从源码可以看到 Integer 也重写了Object的equals方法,
        //变成了判断两个值是否相同
        public boolean equals(Object obj) {
            if (obj instanceof Integer) {//判断你传入进来的数据类型的运行类型,是不是Integer类型或者是Integer类的子类型型
                return value == ((Integer)obj).intValue();
            }
            return false;//如果不是Integer的类型或者不是Integer的子类型就返回false
        }
         */

        //创建了两个Integer对象
        Integer integer1 = new Integer(1000);
        Integer integer2 = new Integer(1000);
        //这里==判断在判断引用类型的时候,判断的是地址是否相等,因此 integer1 和 integer2 都是new出来的,在堆中会有两块不同的空间,因此返回的是false
        System.out.println(integer1 == integer2);//false
        //因为Integer重写了,equals方法,所以判断的是值是否相同,所以返回的是true
        System.out.println(integer1.equals(integer2));//true

        String str1 = new String("jack");
        String str2 = new String("jack");
        //这里==判断在判断引用类型的时候,判断的是地址是否相等,因此 str1 和 str2 都是new出来的,在堆中会有两块不同的空间,因此返回的是false
        System.out.println(str1 == str2);//false
        //因为String重写了,equals方法,所以判断的是值是否相同,所以返回的是true
        System.out.println(str1.equals(str2));//true


    }
}

class A extends B {

}

class B {//父类

}

String类的equals的源码分析

源码分析:

1.首先我们要知道,该equals方法是重写了,Object的equals方法

2.在已进入到方法就去判断,如果当前对象和传入进来的是同一个对象,那么直接返回true

3.判断你传入进来的数据类型的运行类型,是不是String类型或者是String类的子类型型如果是String类型或者是String类的子类型,那么就向下转型

4.如果长度相同,就把字符串,拆成两个不同的字符数组,然后循环的比较数组的值是否先相同,如果其中有一个不相同就返回一个false

5.如果都不成立,说明传入的数据类型的运行类型不是String类型或者不是String类型的子类型

        //看看Jdk的源码 String类的 equals方法
        //String类把Object的equals方法重写了,变成了比较两个字符串值是否相同
        public boolean equals(Object anObject) {
        if (this == anObject) {//判断,如果当前对象和传入进来的是同一个对象
            return true;//返回true
        }
        if (anObject instanceof String) {//判断你传入进来的数据类型的运行类型,是不是String类型或者是String类的子类型型
            String anotherString = (String)anObject;//如果是String类型或者是String类的子类型,那么就向下转型
            int n = value.length;
            if (n == anotherString.value.length) {//如果长度相同
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {//然后一个一个的比较字符
                    if (v1[i] != v2[i])//如果发现两个数组中,有一个字符不相同那么就返回false
                        return false;
                    i++;
                }
                return true;//如果两个字符串的所有字符都相等,则返回true
            }
        }
        return false;//如果比较的不是字符串(也就是传入的数据类型,不是String类型或者不是String类型的子类型),则直接返回false
    }

Object类的equals的源码分析

源码分析:

1.直接判断当前对象和我们传入的对象是否相同,因为==在判断引用类型的时候,判断的是地址是否相同

         //Object 的equals 方法默认就是比较对象地址是否相同
         //也就是判断两个对象是不是同一个对象.
         public boolean equals(Object obj) {
            return (this == obj);//直接判断当前对象和我们传入的对象是否相同,因为==在判断引用类型的时候,判断的是地址是否相同
        }

Integer类的equals的源码分析

源码分析:

1.先判断你传入进来的数据类型的运行类型,是不是Integer类型或者是Integer类的子类型型,如果不是就之间返回false

2.Integer重写了Object类中的方法后,判断的是值是否相同

        //从源码可以看到 Integer 也重写了Object的equals方法,
        //变成了判断两个值是否相同
        public boolean equals(Object obj) {
            if (obj instanceof Integer) {//判断你传入进来的数据类型的运行类型,是不是Integer类型或者是Integer类的子类型型
                return value == ((Integer)obj).intValue();
            }
            return false;//如果不是Integer的类型或者不是Integer的子类型就返回false
        }

equals例题

第一题

思路分析:

1.因为==在判断引用类型的时候,判断的是地址是否相同而person1 和 person2 都是new出来的在堆中也各自的空间,所以返回的是false

2.因为我们重写了equals方法,所以判断的是,两个对象中的值是否相同所以返回true,如果没有重写equals方法,那么默认调用的就是Object的equals方法,判断的就是地址是否相同了

package idea.object_;

import java.util.Objects;

/**
 * equals例题1
 */
public class equalsExercise01 {
    public static void main(String[] args) {
        //判断两个Person对象的内容是否相等,如果两个Person对象各个属性的值都一样就返回true反之返回false
        Person person1 = new Person("jack", 12);
        Person person2 = new Person("jack", 12);
        //因为==在判断引用类型的时候,判断的是地址是否相同而person1 和 person2 都是new出来的在堆中也各自的空间,所以返回的是false
        System.out.println(person2 == person1);//false
        //因为我们重写了equals方法,所以判断的是,两个对象中的值是否相同所以返回true,如果没有重写equals方法,那么默认调用的就是Object的equals方法,判断的就是地址是否相同了
        System.out.println(person1.equals(person2));//true
    }
}

class Person {
    //定义了两个私有的属性
    private String name;
    private int age;

    //构造器
    public Person(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;
    }

    //重写了equals方法
    @Override
    public boolean equals(Object o) {
        if (this == o) {//判断当前对象的地址,和传入的对象的地址是否相同,如果相同返回true
            return true;
        }
        if (o instanceof Person) {//判断我们传入的对象的运行类型是不是Person类型或者是Person类型的子类型
            Person p = (Person) o;//如果是就向下转型
            return p.age == this.age && p.name.equals(this.name);
        }
        return false;//说明不是Person类型,返回false
    }


}

第二题

思路分析:

1.在判断p1==p2时,因为==判断引用类型时 默认判断地址是否相等,所以返回false

2.在判断p1.name.equals(p2.name));时 ,因为p1.name是字符串已经重写了equals方法所以这里判断的 是内容是否相等,因此返回true

3.在判断p1.equals(p2));时因为Person_ 没有重写equals方法所以还是判断的是地址 因为p1是创建的对象并没有重写equals方法所以返回的是false

4.在判断s1.equals(s2));时,因为s1已经是字符串了 已经重写了equals方法,判断的是值是否相同,所以为true

5.在s1 == s2);时,因为String是引用类型所以==判断的还是地址,所以返回false

package idea.object_;

/**
 * equals例题1
 */
public class equalsExercise02 {
    public static void main(String[] args) {
        Person_ p1 = new Person_();
        p1.name = "jack";

        Person_ p2 = new Person_();
        p2.name = "jack";

        System.out.println(p1 == p2);//False==判断引用类型时 默认判断地址是否相等,所以返回false
        System.out.println(p1.name.equals(p2.name));//T 因为p1.name是字符串已经重写了equals方法所以这里判断的 是内容是否相等
        System.out.println(p1.equals(p2));//False 没有重写所以还是判断的是地址 因为p1是创建的对象并没有重写equals方法所以返回的是false

        String s1 = new String("asdf");

        String s2 = new String("asdf");
        System.out.println(s1.equals(s2));//T因为s1已经是字符串了 已经重写了,所以为true
        System.out.println(s1 == s2);//F String是引用类型所以==判断的还是地址
    }
}

class Person_ {
    public String name;
}

hashCode方法

1)提高具有哈希结构的容器的效率!

2)两个引用,如果指向的是同一个对象,则哈希值肯定是一样的!

3)两个引用,如果指向的是不同对象,则哈希值是不一样的

4)哈希值主要根据地址号来的!,不能完全将哈希值等价于地址。

思路分析:

1.因为aa 和aa2都是new出来的,在堆中有不同的空间,所以他们的hashCode不同,aa3是aa赋给给他的,因此指向的是同一块空间,因此,aa和aa3的hashCode相同

package idea.object_;

public class HashCode_ {
    public static void main(String[] args) {

        AA aa = new AA();
        AA aa2 = new AA();
        AA aa3 = aa;
        //因为aa 和aa2都是new出来的,在堆中有不同的空间,所以他们的hashCode不同,aa3是aa赋给给他的,因此指向的是同一块空间,因此,aa和aa3的hashCode相同
        System.out.println("aa.hashCode()=" + aa.hashCode());
        System.out.println("aa2.hashCode()=" + aa2.hashCode());
        System.out.println("aa3.hashCode()=" + aa3.hashCode());


    }
}

class AA {
}

toString方法

基本介绍

默认返回:全类名+@+哈希值的十六进制,子类往往重写toString方法,用于返回对象的属性信息

重写toString方法,打印对象或拼接对象时,都会自动调用该对象的toString形式

当直接输出一个对象时,toString方法会被默认的调用,比如 System.out.println(monster);就会默认调用 monster.toString()

代码演示:

1.如果不重写toString()方法,那么在输出的时候,输出的就是包名,类名,加上地址

package idea.object_;

public class ToString_ {
    public static void main(String[] args) {

        /*
        Object的toString() 源码
        (1)getClass().getName() 类的全类名(包名+类名 )
        (2)Integer.toHexString(hashCode()) 将对象的hashCode值转成16进制字符串
        public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
         */

        Monster monster = new Monster("jack", "公司领导", 1000);
        System.out.println(monster.toString() + " hashcode=" + monster.hashCode());

        //如果不重写toString()方法,那么在输出的时候,输出的就是包名,类名,加上地址
        System.out.println(monster); //等价 monster.toString()
    }
}

class Monster {
    //定义了三个属性
    private String name;
    private String job;
    private double sal;

    public Monster(String name, String job, double sal) {
        this.name = name;
        this.job = job;
        this.sal = sal;
    }

    //重写toString方法, 输出对象的属性
    @Override
    public String toString() { //重写后,一般是把对象的属性值输出,当然程序员也可以自己定制
        return "Monster{" +
                "name='" + name + '\'' +
                ", job='" + job + '\'' +
                ", sal=" + sal +
                '}';
    }
}

finalize方法

1.当对象被回收时,系统自动调用该对象的finalize方法。子类可以重写该方法,做一些释放资源的操作

2.什么时候被回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用 finalize方法。

3.垃圾回收机制的调用,是由系统来决定(即有自己的GC算法),也可以通过System.gc()主动触发垃圾回收机制,测试:Car [name]

代码演示:

1.当把bmw置成null时,这是bmw原来指向堆中的空间就没有在指向了,因此这时 car对象就是一个垃圾,垃圾回收器就会回收(销毁)对象, 在销毁对象前,会调用该对象的finalize方法

2.注意是在我们程序退出后,才去执行finalize中的代码

package idea.object_;

/**
 * 演示 Finalize的用法
 */
public class Finalize_ {
    public static void main(String[] args) {

        //创建了一个car对象
        Car bmw = new Car("宝马");
        //当把bmw置成null时,这是bmw原来指向堆中的空间就没有在指向了,因此这时 car对象就是一个垃圾,垃圾回收器就会回收(销毁)对象, 在销毁对象前,会调用该对象的finalize方法
        //,我们就可以在 finalize中,写自己的业务逻辑代码(比如释放资源:数据库连接,或者打开文件..)
        //,如果程序员不重写 finalize,那么就会调用 Object类的 finalize, 即默认处理
        //,如果程序员重写了finalize, 就可以实现自己的逻辑
        bmw = null;
        System.gc();//主动调用垃圾回收器

        System.out.println("程序退出....");
        //注意是在我们程序退出后,才去执行finalize中的代码
    }
}

//定义了一个汽车类
class Car {
    //定义了一个 属性
    private String name;

    //构造器
    public Car(String name) {
        this.name = name;
    }

    //为了看到效果,我们重写finalize方法
    @Override
    protected void finalize() throws Throwable {
        System.out.println("我们销毁了一辆" + name + "汽车");


    }
}

猜你喜欢

转载自blog.csdn.net/weixin_53616401/article/details/129729028