zoukankan      html  css  js  c++  java
  • 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;
        }
    }
  • 相关阅读:
    VC中隐藏和显示IDC_STATIC
    在VC++中使用Tab Control控件
    关于CTreeView中CTreeCtrl空间的使用
    MFC打开/保存文件对话框:CFileDialog
    Python自学笔记3-数据类型
    MFC实现原理
    VS2008 MFC内部工作原理
    MFC视频教程(孙鑫)学习笔记2-掌握C++
    MFC视频教程(孙鑫)学习笔记1-Windows程序内部运行原理
    error C2440: “=”: 无法从“const char [11]”转换为“LPCWSTR”
  • 原文地址:https://www.cnblogs.com/xlwu/p/13127209.html
Copyright © 2011-2022 走看看