JDK中的Object类

1 JDK类库的根类:Object
    1.1 这个老祖宗类中的方法我们需要先研究一下,因为这些方法都是所有子类通用的。
    任何一个类默认继承Object。就算没有直接继承,最终也会间接继承。
    
    1.2 Object类当中有哪些常用的方法?
        我们去哪里找这些方法呢?
            第一种方法:去源代码当中。(但是这种方式比较麻烦。源代码也比较难)
            第二种方法:去查阅java的类库的帮助文档。
            
        什么是API?
            应用程序编程接口。(Application Program Interface)
            每个JDK的类库就是一个javase的API。
            每一个API都会配置一套API帮助文档。
            SUN公司提前下好的这套类库就是API。(一般每一份API都对应一份API帮助文档。)
            
        目前为止我们只需要知道这几个方法即可。
        protected Object clone()  //负责对象克隆的
        int hashCode() // 获取对象哈希值的一个方法。
        String toString()  // 将对象转换成字符串形式
        boolean equals(Object obj)  // 获取对象哈希值的一个方法
        protected void finalize()  //垃圾回收器负责调用的方法
        
    1.3 toString()方法
        以后所有类的toString()方法是需要重写的。
        重写规则,越简单越明了就好。
        
        System.out.println(引用);这个会自动调用“引用.”的toString()方法。
        
        String类是SUN写的,toString()方法已经重写了。
        
        String类是SUN写的,toString方法已经重写了。
        
    1.4 equals()方法
        以后所有类的equals方法也需要重写,因为Object中的equals方法比较的是两个对象的内存地址,我们应该比较内容,所以需要重写。
        
        重写规则:自己定,主要看是什么和什么相等时表示两个对象相等。
        
        基本数据类型比较使用==
        对象和对象比较:调用equals方法
        
        String类是SUN编写的,所以String类的equals方法重写了。
        以后判断两个字符串是否相等,最好不要使用==,要调用字符串对象的equals方法。
        
        注意:重写equals方法的时候要彻底。
        
    1.5 finalize()方法。
        这个方法是protected修饰的,在Object类中这个方法的源代码是?
            protected void finalize() throws Throwable{ }
 
 
 
重写toString()方法的案例:
/*
* 关于Object类中的toString()方法
*   1 源代码长什么样?
*   public String toString(){
*       return this.getClass().getName() + "@" + Integer.toHexString(hashCode());
*   }
*   源代码上toString()方法默认实现是:
*       类名@对象的内存地址转换成十六进制的形式
*
*   2 SUN公司设计toString()方法的目的是什么?
*       toString()方法的作用是:
*           toString()方法的设计目的是:通过调用这个方法可以将一个“java对象”转换成“字符串”的形式。
*
*   3 其实SUN公司开发java语言的时候,建议所有的子类都去重写toString()方法。
*   toString()方法应该是一个简洁的、详实的、易阅读的。
* */
public class Test01 {
    public static void main(String[] args) {
        MyTime myTime = new MyTime(1970,1,1);
        // 一个日期对象转换成字符串形式的话,我可能还是希望看到具体的日期信息。
        String s1 = myTime.toString();


        //MyTime类重写toString()方法之前
        System.out.println(s1);// MyTime@十六进制   MyTime@10f87f48


        //MyTime类重写toString()方法之后
        System.out.println(myTime.toString());// 1970年1月1日


        // 注意:输出引用的时候,会自动调用该引用的toString()方法。
        System.out.println(s1);
    }
}


class MyTime{
    int year;
    int month;
    int day;


    public MyTime() {
    }


    public MyTime(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }


    // 重写toString()方法
    // 这个toString()方法怎么重写呢?
    // 越简洁越好,可读性越强越好
    // 向简洁的、详实的、易阅读的方向发展


    public String toString(){
       return this.year + "年" + this.month + "月" + this.day + "日";
    }
}

 

重写Object中的equals方法案例:

/*
* 关于Object类中的equals()方法
*   1 equals方法的源代码
*   public boolean equals(Object obj){
*       return (this == obj);
*   }
*   以上这个方法是Object类的默认实现
*
*   2 SUN公司设计equals方法的目的是什么?
*       以后编程的过程中,都要通过equals方法来判断两个对象是否相等。
*       equals方法是判断两个对象是否是相等的。
*
*   3 我们需要研究一下Object类给的这个默认的equals方法够不够用!!!!
*       在Object类中的equals方法当中,默认采用的是“==”判断两个java对象是否相等。
*       而“==”判断的是两个java对象的内存地址,我们应该判断两个java对象的内容是否相等,所以老祖宗的equals方法不够用。
*       需要子类重写equals。
*
*   4 判断两个java是否相等,不能用“==”,因为“==”比较的是两个对象的内存地址。
* */
public class Test02 {
    public static void main(String[] args) {
        // 判断两个基本数据类型的数据是否相等直接使用“==”就行。
        int a = 100;
        int b = 100;
        // 这个“==”是判断a中保存的100和b中保存的100是否相等。
        System.out.println(a == b);// true 相等  false 不相等


        // 判断两个java对象是否相等,我们怎么办?能直接使用“==”吗?
        // 创建一个日期对象是:1970年1月1日。
        MyTime1 t1 = new MyTime1(1970,1,1);// MyTime t1 = 0x1234;
        // 创建一个新的日期对象,但表示的日期也是:1970年1月1日。
        MyTime1 t2 = new MyTime1(1970,1,1);// MyTime t1 = 0x2345;


        // 测试一下:比较两个对象是否相等,能不能使用“==”???
        // 这里的“==”判断的是:t1中保存的对象地址和t2中保存的对象地址是否相等。
        System.out.println(t1 == t2);//false


        // 重写Object equals方法之前(比较的是对象的内存地址)
        /*boolean flag = t1.equals(t2);
        System.out.println(flag);*/


        // 重写Object equals方法之后(比较的是内容)
        boolean flag = t1.equals(t2);
        System.out.println(flag);


        MyTime1 t3 = new MyTime1(1970,1,22);
        boolean flag1 = t1.equals(t3);
        System.out.println(flag1);


        // 我们这个程序有bug吗?可以运行,但是效率怎么样?低(怎么改造)
        MyTime1 t4 = null;
        System.out.println(t1.equals(t4));
    }
}


class MyTime1{
    int year;
    int month;
    int day;


    public MyTime1() {
    }


    public MyTime1(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }


    // 默认的equals方法
    /*public boolean equals(Object obj){
       return (this == obj);
    }*/


    // 重写Object类的equals方法
    // 怎么重写?赋值黏贴。相同的返回值类型、相同的方法名、相同的形式参数列表。
    // equals到底应该怎么重写?你自己定,你认为两个对象什么相等的时候表示相等,你就怎么重写。
    /*public boolean equals(Object obj){
        // 当年相同,月相同,日也相同的时候,表示两个日期相同。
        // 两个对象相等。
        // 获取第一个日期的年月日
        // 获取第二个日期的年月日
        // 开始比对


        // 获取第一个日期的年月日
        int year1 = this.year;
        int month1 = this.month;
        int day1 = this.day;


        // 获取第二个日期的年月日
        *//*int year2 = obj.year;
        int month2 = obj.month;
        int day2 = obj.day;*//*


        if (obj instanceof MyTime1){
            MyTime1 t = (MyTime1)obj;
            int year2 = t.year;
            int month2 = t.month;
            int day2 = t.day;


            if (year1 == year2 && month1 == month2 && day1 == day2){
                return true;
            }
        }


        // 如果程序能够执行到此处表示日期不相等。
        return false;
    }*/


    // 改良equals方法
    /*public boolean equals(Object obj){
        // 如果obj是空,直接返回false
        if (obj == null){
            return false;
        }


        // 如果obj的类型不是MyTime1的话,也返回false
        if(!(obj instanceof MyTime1)){
            return false;
        }


        // 如果this和obj保存的内存地址相同,没必要比较了,直接返回true。
        // 内存地址相同的时候指向的堆内存的对象肯定是同一个咯。
        if (this == obj){
            return true;
        }


        // 程序能够执行到此处说明什么?
        // 说明obj不是null。obj是MyTime1类型。
        MyTime1 t = (MyTime1) obj;
        if(this.year == t.year && this.month == t.month && this.day == t.day){
            return true;
        }


        // 程序能到这里返回false
        return false;
    }*/


    // 再次改良
    /*public boolean equals(Object obj){
        // 如果obj是空,直接返回false
        if (obj == null){
            return false;
        }


        // 如果obj的类型不是MyTime1的话,也返回false
        if(!(obj instanceof MyTime1)){
            return false;
        }


        // 如果this和obj保存的内存地址相同,没必要比较了,直接返回true。
        // 内存地址相同的时候指向的堆内存的对象肯定是同一个咯。
        if (this == obj){
            return true;
        }


        // 程序能够执行到此处说明什么?
        // 说明obj不是null。obj是MyTime1类型。
        MyTime1 t = (MyTime1) obj;
        return this.year == t.year && this.month == t.month && this.day == t.day;
    }*/


    // 再再次改良
    public boolean equals(Object obj){
        // 如果obj是空,直接返回false
        if (obj == null && !(obj instanceof MyTime1)){
            return false;
        }


        // 如果this和obj保存的内存地址相同,没必要比较了,直接返回true。
        // 内存地址相同的时候指向的堆内存的对象肯定是同一个咯。
        if (this == obj){
            return true;
        }


        // 程序能够执行到此处说明什么?
        // 说明obj不是null。obj是MyTime1类型。
        MyTime1 t = (MyTime1) obj;
        return this.year == t.year && this.month == t.month && this.day == t.day;
    }
}

 

 

重写Object中equals()方法案例:

import java.util.Objects;


// String对象比较的时候必须使用equals方法。
public class Test03 {
    public static void main(String[] args) {
        /*Student a = new Student("123");
        Student b = new Student("123");


        System.out.println(a == b);
        System.out.println(a.equals(b));*/


        Student a = new Student(111,new String("123"));
        Student b = new Student(111,new String("123"));


        System.out.println(a == b);
        System.out.println(a.equals(b));
    }
}


class Student{
    // 学号
    int no; // 基本数据类型,比较时用==
    // 所在学校
    String school;// 引用数据类型,比较时用equals方法


    public Student() {
    }


    public Student(int no, String school) {
        this.no = no;
        this.school = school;
    }


    // 重写toString()方法
    public String toString(){
        return "学号" + no + ",所在学校名称" + school;
    }


    // 重写equals方法
    // 需求:当一个学生的学号相等,并且学校相同时,表示同一个学生
    // 思考:这个equals该怎么重写呢?
    // equals方法的编写模式都是固定的。架子都是差不多的
    public boolean equals(Object obj) {


        if (obj == null && !(obj instanceof Student)){
            return false;
        }


        if (this == obj){
            return true;
        }


        Student s = (Student)obj;
        return this.no == s.no && this.school.equals(s.school);


        // 字符串用双等号比较可以吗?
        // 不可以
        //return this.no == s.no && this.school == s.school;
    }
}

 

重写Object中equals()方法案例:

/*
* java语言当中的字符串String有没有重写toString方法,有没有重写equals方法。
*
* 总结:
*   1 String类已经重写了equals方法,比较两个字符串不能使用==,必须使用equals。
*   equals是通用的。
*
*   2 String类已经重写了toString()方法。
*
*   大结论:
*       java中什么类型的数据可以使用“==”来判断。
*           java中基本数据类型比较是否相等,使用==
*
*       java中什么类型的数据需要使用equals来判断。
*           java中所有的引用数据类型统一使用equals方法来判断是否相等。
*
*   这是规矩。
* */
public class Test04 {
    public static void main(String[] args) {


        // 大部分情况下,采用这样的方式创建字符串对象
        String s1 = "Hello";
        String s2 = "abc";


        // 实际上String也是一个类,不属于基本数据类型。
        // 既然String是一类,那么一定存在构造方法
        String s3 = new String("Test1");
        String s4 = new String("Test1");


        // new两次,两个对象内存地址,s3保存的内存地址和s4保存的内存地址不同。
        // == 判断的是内存地址。不是内容。
        System.out.println(s3 == s4);//false


        // 比较两个字符串能不能使用双等号?
        // 不能,必须调用equals方法。
        // equals才是判断对象的值。
        // String类已经重写equals方法了
        System.out.println(s3.equals(s4));


        // String类有没有重写toString()方法呢?
        String s = new String("xlWu");
        // 如果String没有重写toString()方法,输出结果:java.lang.String@十六进制地址
        // 经过测试:String类已经重写了toString()方法
        System.out.println(s.toString());//xlWu
        System.out.println(s);//xlWu
    }
}

 

重写Object中equals()方法要重写彻底案例:

import java.util.Objects;
// equals方法重写的时候要彻底。
public class Test05 {
    public static void main(String[] args) {
        //Address address = new Address("重庆","渝澳大道","招商锦星汇");
        User u = new User("zhangsan",new Address("重庆","渝澳大道","招商锦星汇"));
        User u1 = new User("zhangsan",new Address("重庆","渝澳大道","招商锦星汇"));


        System.out.println(u.equals(u1));


        User u2 = new User("zhangsan",new Address("重庆","渝澳大道","读书一村"));
        System.out.println(u.equals(u2));


    }
}


class User{
    //用户名
    String name;
    //地址
    Address addr;


    public User() {
    }


    public User(String name, Address addr) {
        this.name = name;
        this.addr = addr;
    }


    // 重写equals方法
    // 重写规则:当一个用户的用户名和家庭住址都相同,表示同一个用户。
    // 这个equals判断的是User对象和User对象是否相等。
    public boolean equals(Object obj) {
        // 用户名和用户名相同,住址和住址相同的时候,认定是同一个用户。
        if(obj == null && !(obj instanceof User)){
            return false;
        }


        if (this == obj){
            return true;
        }


        User user = (User)obj;
        if (this.name.equals(user.name) && this.addr.equals(user.addr)){
            return true;
        }


        return false;
    }
}


class Address{
    String city;
    String street;
    String zipcode;


    public Address() {
    }


    public Address(String city, String street, String zipcode) {
        this.city = city;
        this.street = street;
        this.zipcode = zipcode;
    }


    // 注意:这里并没有写
    // 这里的equals方法判断的是:Address对象和Address对象是否相等。
    public boolean equals(Object obj){
        if (obj == null && !(obj instanceof Address)){
            return false;
        }


        if (this == obj){
            return false;
        }
        Address address = (Address)obj;
        if (this.city.equals(address.city) && this.street.equals(address.street) && this.zipcode.equals(address.zipcode)){
            return true;
        }
        return false;
    }
}

 

 
Object中finalize()方法案例:
/*
* 关于Object类中的finalize()方法(非重点)
*   1 在Object类中的源码:
*       protected void finalize() throws Throwable{ }
*
*   GC:负责调用finalize()方法。
*
*   2 finalize()方法只有一个方法体,里面没有代码,而且这个方法是protected修饰的。
*
*   3 这个方法不需要程序员手动调用,JVM的垃圾回收器负责调用这个方法。
*   不像equals() toString(),equals()和toString()方法是需要你写代码调用的。
*   finalize()只需要重写,重写完将来自动还有程序来调用。
*
*   4 finalize()方法的执行机制:
*       当一个java对象即将被垃圾回收器回收的时候,垃圾回收器负责finalize()方法
*
*   5 finalize()方法实际上是SUN公司为java程序员准备的一个世纪,垃圾销毁机。
*   如果希望在对象销毁时机执行一段代码的话,这段代码要写到finalize()方法中。
*
*   6 静态代码块的作用是什么?
*   static{
*       ...
*   }
*   静态代码块在类加载时刻执行,并且只执行一次。
*   这是一个SUN准备的类加载时机
*
*   finalize()方法同样也是SUN为程序员准备的一个时机。
*   这个时机是垃圾回收时机。
*
*   7 提示:
*       java中的垃圾回收器不是轻易启动的,垃圾太少,或者时间没到,种种条件下,有可能启动,也有可能不启动。
* */
public class Test06 {
    public static void main(String[] args) {
        // 创建对象
        Person person = new Person();


        // 怎么把Person对象变成垃圾?
        person = null;


        // 多制造点垃圾
        for (int i = 0; i < 100000000; i++){
            Person p = new Person();
            p = null;
        }


        // 有一段代码可以建议垃圾回收器启动
        System.gc();// 建议启动垃圾回收器,(只是建议,可能不启动,也可能启动。启动概率高了一些。)
    }
}


/*
* 项目开发中有这样的业务需求:所有对象在JVM中被释放的时候,请记录一下释放时间!!!
* 记录对象被是释放的时间点,这个负责记录的代码写到哪里?
* 写到finalize()方法中。
* */
class Person{


    // 重写finalize()方法
    // Person类型的对象被垃圾回收器回收的时候,垃圾回收器负责调用:p.finalize()。
    protected void finalize() throws Throwable {
        // this代表当前对象
        System.out.println(this + "即将被销毁!");
    }
}

 

Object中的hashCode()方法案例:
 
/*
* hashCode方法
*   在Object中的hashCode方法是怎样的?
*       public native int hashCode();
*   这个方法不是抽象方法,带有native关键字,底层调用c++程序
*
*   hashCode()方法返回的是哈希值:
*       实际上就是一个java对象的内存地址,经过哈希算法,得出一个值。
*       所以hashCode()方法的执行结果可以等同看做一个java对象的内存地址。
* */
public class Test07 {
    public static void main(String[] args) {
        Object object = new Object();
        int hashCodeValue = object.hashCode();


        // 对象内存地址经过哈希算法转换的一个数字,可以等同看做内存地址
        System.out.println(hashCodeValue);//1915910607


        MyClass myClass = new MyClass();
        int hashCodeValue1 = myClass.hashCode();
        System.out.println(hashCodeValue1);//189568618
    }
}


class MyClass{ }

 

利用IDEA重写Object中的toString()和equals()方法案例:
 
import java.util.Objects;


/*IDEA自动生成重写方法*/


public class MyTime4 {
    private int year;
    private int month;
    private int day;


    public MyTime4() {
    }


    public MyTime4(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }


    public int getYear() {
        return year;
    }


    public void setYear(int year) {
        this.year = year;
    }


    public int getMonth() {
        return month;
    }


    public void setMonth(int month) {
        this.month = month;
    }


    public int getDay() {
        return day;
    }


    public void setDay(int day) {
        this.day = day;
    }


    public String toString() {
        return "MyTime4{" +
                "year=" + year +
                ", month=" + month +
                ", day=" + day +
                '}';
    }


    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MyTime4 myTime4 = (MyTime4) o;
        return year == myTime4.year &&
                month == myTime4.month &&
                day == myTime4.day;
    }
}

 

posted @ 2020-06-14 21:47  xlwu丶lz  阅读(261)  评论(0编辑  收藏  举报