首页 > 其他 > 详细

Object类

时间:2020-07-03 09:10:04      阅读:60      评论:0      收藏:0      [点我收藏+]

Object类

Object类概述

  • Object类是JDK类库的根类
  • 老祖宗类中的方法需要研究一下,因为这些方法都是所有子类通用的。
  • 任何一个类默认继承Object。就算没有直接继承,最终也会间接继承。

什么是API ?

  • API:应用程序编程接口。(Application Program Interface)
  • 整个JDK的类库就是一个javase的API。每一个API都会配置一套API帮助文档。SUN公司提前写好的这套类库就是API。(一般每一份API都对应一份API帮助文档。)

Object类当中常用的方法

在哪查看这些方法

  • 第一种方法:去源代码当中。(但是这种方式比较麻烦,源代码也比较难)
  • 第二种方法:去查阅java的类库的帮助文档。

目前为止我们只需要知道这几个方法即可

  • protected Object clone() // 负责对象克隆的。
  • int hashCode() // 获取对象哈希值的一个方法。
  • boolean equals(Object obj) // 判断两个对象是否相等
  • String toString() // 将对象转换成字符串形式
  • protected void finalize() // 垃圾回收器负责调用的方法

toString方法

  • 源代码

    public String toString(){
        return this.getClass().getName + Integer.toHexString(hashCode());
    }
    

    源代码上toString()方法的默认实现是:类名@对象的内存地址转换为十六进制的形式。

  • toString()方法的作用

    • toString()方法的设计目的是:通过调用这个方法可以将一个“Java对象”转换成“字符串表示形式”
  • 其实SUN公司开发Java语言的时候,建议所有的子类都去重写toString()方法。toString()方法应该是一个简洁的、详实的、易阅读的。以后所有类的toString()方法是需要重写的。重写规则,越简单越明了就好。

    public class Test01 {
        public static void main(String[] args) {
            MyTime t1 = new MyTime(2020,7,2);
            String s1 = t1.toString();
            //MyTime类重写toString()方法之前
            //System.out.println(s1);//MyTime@75412c2f
            //MyTime类重写toString()方法之后
            System.out.println(s1);//2020年7月2日
            //输出引用的时候会自动调用该引用的toString()方法。
            System.out.println(t1);//2020年7月2日
        }
    }
    
    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()方法
        //重写的越简洁越好,可读性越强越好
        public String toString() {
            return this.year + "年" + this.month + "月" + this.day + "日";
        }
    }
    
  • System.out.println(引用); 这里会自动调用“引用”的toString()方法。

    MyTime t1 = new MyTime(2020,7,2);
    String s1 = t1.toString();
    System.out.println(s1);//2020年7月2日
    //输出引用的时候会自动调用该引用的toString()方法。
    System.out.println(t1);//2020年7月2日
    

equals方法

关于Object类中的equals方法

  1. equals()方法的源代码

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

    以上是这个方法的默认实现。在Object类中的equals()方法当中,默认采用的是“==”判断两个Java对象是否相等。

  2. SUN公司设计equals的目的是什么?

    • 以后编程的过程中,都要通过equals()方法来判断两个对象是否相等。equals()方法是判断两个对象是否相等的。
  3. Object类给的这个默认方法的equals()方法不够用。在Object类中的equals()方法当中,默认采用的是==判断两个Java对象是否相等。而==判断的是两个Java对象的内存地址,我们应该判断两个Java对象的内容是否相等,所以老祖宗的equals()方法不够用。

  4. 判断两个Java对象是否相等,不能使==,因为==比较的是两个对象的内存地址。

    //      判断两个基本数据类型的数据是否相等直接使用“==”
            int a = 100;
            int b = 100;
    //        这个“==”是判断a中保存的100和b中保存的100是否相等
            System.out.println(a == b);
    
    //        创建一个日期对象:2020年7月2日
            MyTime t1 = new MyTime(2020, 7, 2);
    //        创建一个新的日期对象:2020年7月2日
            MyTime t2 = new MyTime(2020, 7, 2);
    //        这里的“==”判断的是:t1中保存的对象内存地址和t2中保存的对象内存地址是否相等
            System.out.println(t1 == t2);
    
  5. 重写equals()方法

    public class Test01 {
        public static void main(String[] args) {
    //        创建一个日期对象:2020年7月2日
            MyTime t1 = new MyTime(2020, 7, 2);
    //        创建一个新的日期对象:2020年7月2日
            MyTime t2 = new MyTime(2020, 7, 2);
    
            //重写Object的equals()方法之前(比较的是对象的内存地址)
            /*boolean flag = t1.equals(t2);
            System.out.println(flag);*/
    
            //重写Object类的equals()方法之后(比较的是内容)
            boolean flag = t1.equals(t2);
            System.out.println(flag);
        }
    }
    
    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;
        }
        //默认的equals()方法
        /*public boolean equals(Object obj){
            return (this = obj);
        }*/
    
        //重写Object的equals()方法
        public boolean equals(Object obj) {
    //        获取第一个日期的时间
            int year1 = this.year;
            int month1 = this.month;
            int day1 = this.day;
    //        获取第二是日期的时间
            if (obj instanceof MyTime) {
                MyTime t = (MyTime) obj;
                int year2 = t.year;
                int month2 = this.month;
                int day2 = this.day;
                if(year1==year2 && month1==month2 && day1==day2){
                    return true;
                }
            }
            //程序能执行到此处说明日期不相等
            return false;
        }
    }
    
    • 改良重写的equals()方法
    //改良equals()方法
        public boolean equals(Object obj){
            //如果obj是空的,直接返回false
            if(obj==null){
                return false;
            }
            //如果obj不是一个MyTime,就没必要比较了,直接返回false
            if(!(obj instanceof MyTime)){
                return false;
            }
            //如果this和obj保存的内存地址相同,就没必要比较了,直接返回true
            //内存地址相同的时候指向的堆内存的对象肯定是同一个
            if(this==obj){
                return true;
            }
            //程序执行到此处说明,obj不是null,obj是MyTime类型
            MyTime t= (MyTime)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是空的,或者obj不是一个MyTime,就没不必要比较了,直接返回false
              if (obj == null || !(obj instanceof MyTime)) {
                  return false;
              }
              //如果this和obj保存的内存地址相同,就没必要比较了,直接返回true
              //内存地址相同的时候指向的堆内存的对象肯定是同一个
              if (this == obj) {
                  return true;
              }
              //程序执行到此处说明,obj不是null,obj是MyTime类型
              MyTime t = (MyTime) obj;
              return this.year == t.year && this.month == t.month && this.day == t.day;
          }
      
  6. String对象比较的时候必须使用equals()方法

    /String对象比较的时候必须使用equals()方法
    public class Test02 {
        public static void main(String[] args) {
            Student s1 = new Student(11, "上元中学");
            Student s2 = new Student(11, "上元中学");
            System.out.println(s1 == s2);//false
            System.out.println(s1.equals(s2));//true
        }
    }
    
    class Student {
        int no;//学号
        String school;//所在学校
    
        public Student() {
        }
    
        public Student(int no, String school) {
            this.no = no;
            this.school = school;
        }
    
        //重写toString()方法
        public String toString() {
            return "学号" + no + ",所在学校名称" + school;
        }
    
        //    重写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);
        }
    }
    
  7. equals()方法的重写要彻底。

    //equals()方法的重写要彻底。
    public class Test02 {
        public static void main(String[] args) {
            User u1 = new User("xiaoqiang", new Address("南京", "江宁区", "上元大街"));
            User u2 = new User("xiaoqiang", new Address("南京", "江宁区", "上元大街"));
            System.out.println(u1.equals(u2)); //true
        }
    }
    
    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 u = (User) obj;
            return this.name.equals(u.name) && this.addr.equals(u.addr);
        }
    }
    
    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()方法
    //    这里的equals()方法判断的是:Address对象和Address对象是否相等。
    
    //    现在要重写equals()方法
        public boolean equals(Object obj){
            if(obj==null || !(obj instanceof Address)) return false;
            if(this==obj) return true;
    //        城市相同,街道相同,邮编相同,认定地址相同
            Address a=(Address)obj;
            return this.city.equals(a.city) && this.street.equals(a.street) && this.zipcode.equals(a.zipcode);
        }
    }
    

Object的finalize方法(非重点,了解即可)

关于Object类中的finalize()方法

  • 在Object类中的源代码:protected void finalize() throws Throwable{}finalize()方法只有一个方法体,里面没有代码,而且这个方法是protected修饰的。

  • 这个方法不需要程序员手动调用,JVM的垃圾回收器负责手动调用这个方法。不像equals()方法和toString()方法是需要程序员手写代码调用的。finalize()方法只需要重写,重写完将来会自动有程序调用。

  • finalize()方法的执行时机:当一个Java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用finalize()方法。

  • finalize()方法实际上是SUN公司为java程序员准备的一个时机,垃圾销毁时机,如果希望在对象销毁时机执行一段代码的话,这段代码要写到finalize()方法当中。

  • 静态代码块在类加载时刻执行,并且只执行一次,这是SUN公司准备的一个类加载时机。finalize()方法同样也是SUN公司为程序员准备的一个时机,这个时机是垃圾回收时机。

  • Java中的垃圾回收器不是轻易启动的,垃圾太少,或者时间没到,种种条件下,有可能启动,也有可能不启动。

    public class Test01 {
        public static void main(String[] args) {
            for (int i = 0; i < 1000000; i++) {
                Person p = new Person();//创建对象
    //        把Person对象变成垃圾
                p = null;
            }
        }
    }
    
    //项目开发中有这样的需求:所有对象在JVM中被释放的时候,记录一下施放时间
    //记录对象被释放的时间点,这个负责记录的代码写在finalize()方法中。
    class Person {
        //    重写finalize()方法
    //    Person对象被垃圾回收器回收的时候,垃圾回收器负责调用:p.finalize()
        protected void finalize() throws Throwable {
            System.out.println(this + "即将被销毁!");
        }
    }
    
    //        有一段代码可以建议垃圾回收器启动
    //        只是建议,可能不启动,也可能启动,只是启动的概率会大很多。
            System.gc();//建议启动垃圾回收器
    

Object的hashCode方法

  • 在Object中的源代码:public native int hashCode();这个方法不是抽象方法,带有native关键字,底层调用c++程序。

  • hashCode()方法返回的是哈希码:实际上就是一个Java对象的内存地址,经过哈希算法,得出的一个值。所以hashCode()方法的执行结果可以等同看作一个Java对象的内存地址。

    public class Test01 {
        public static void main(String[] args) {
            Object o = new Object();
            int hashCodeValue = o.hashCode();
    //        对象内存地址经过哈希算法转换成为一个数字,可以等同看作内存地址。
            System.out.println(hashCodeValue);//1355531311
    
            MyClass mc = new MyClass();
            int hashCodeValue2 = mc.hashCode();
            System.out.println(hashCodeValue2);//42121758
        }
    }
    class MyClass {
    }
    

String类重写了toString方法和equals方法

  • java语言中的字符串String重写了equals()方法。比较两个字符串不能使用==,必须使用equals()方法,equals是通用的。

    public class Test01 {
        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()方法
    //        String类已经重写equals()方法
            System.out.println(s3.equals(s4));
        }
    }
    
  • String已经重写了toString()方法

     String x = new String("夜空星满");
    //如果String没有重写toString()方法,输出结果:java.lang.String@十六进制的地址
    //经过测试:String类已经重写了toString()方法
    System.out.println(x.toString());//夜空星满
    System.out.println(x);//夜空星满
    

重要总结

  • Java中基本数据类型比较是否相等,使用==进行判断。
  • Java中所有的引用数据类型统一使用equals()方法来判断是否相等.

Object类

原文:https://www.cnblogs.com/yxc-160206/p/13228158.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!