• 11.JAVA-Object类之finalize(),clone(),toString()等方法覆写


    1.Object介绍

    Object类是一个特殊的类,是所有类(包括数组,接口 )的父类,如果一个类没有用extends明确指出继承于某个类,那么它默认继承Object类,所以可以通过向上转型的方法使用类型为Object的变量指向任意类型的对象。

    • 本章主要实现覆写Object类的clone(),toString()equals(),finalize()等最重要的方法。

     

    2.覆写finalize()

     

    在之前我们学习析构方法时,便讲过finalize().

    参考之前学的finallize方法示例:3.JAVA-方法重载,类的封装,构造/析构方法

    从本章学习开始,才发现原来是通过覆写Object类的finalize()实现的垃圾回收.

     

    3.覆写clone()

     

    如上图所示,该方法是protected类型,不能在类外直接调用.该方法主要的功能是实现两个对象深拷贝(两个对象地址都是独立的),我们平时写的代码"对象1 = 对象2"其实是浅拷贝(两个对象地址是一致的,修改对象1便等于修改对象2).

    3.1 注意事项

    覆写clone之前,我们需要实现Cloneable接口(该接口在java中自带的,不需要自己写),如果不实现的话,则调用clone时,将会报异常.并且覆写clone时,可以将clone改为public类型,介绍如下所示:

     

    3.2 覆写Clone代码如下

    class Person implements Cloneable   //实现Cloneble
    {
             public String name;
    
             public Person(String name)
             {
                      this.name = name ;
             }
    
             public Object clone(){             //覆写clone
                      Person o = null;
                      try{
                              o = (Person)super.clone();
                      }catch(CloneNotSupportedException e){
                              e.printStackTrace();
                      }
                      return o;
             }
    }
    
    public class Test{
             public static void main(String args[])
             {
                      Person p1=new Person("小王");
                      Person p2 = p1;
                      p2.name = "小张";
                      System.out.println("p1 name:"+p1.name);
                      System.out.println("p2 name:"+p2.name);
    
                      System.out.println("通过Object超类下的clone方法实现深拷贝:");
                      p2  = (Person)p1.clone();
                      p2.name = "小王";
                      System.out.println("p1 name:"+p1.name);
                      System.out.println("p2 name:"+p2.name);
             }
    }

    运行打印:

     

    如上图所示,可以看到直接对对象进行赋值,其实是浅拷贝,而通过clone()则实现的深拷贝

     

    4.覆写toString()

     

    覆写toString()的意义在于:

    • 方便打印一个对象的具体信息,并且由于是覆写的Object类,所以通过向上转换后,则可以确定参数的统一.方便程序设计.

    4.1 覆写toString代码如下

    class Teacher
    {   
          String name;
          int  age;
          Teacher(String name,int  age)
          {
                this.name = name;
                this.age  = age;
          }
          public String toString()
          {
                return "老师名字:"+name+" 年龄:"+age;
          }
    }
    
    class Student
    {   
          String name;
          String clas;
          Student(String name,String clas)
          {
                this.name = name;
                this.clas = clas;
          }
          public String toString()
          {
                return "学生名字:"+name+"   班级:"+clas;
          }
    }
    
    public class Test
    {
          public static void printDesc(Object obj)       //打印描述
          {
                System.out.println(obj.toString());
          }
    
          public static void main(String args[]){
                printDesc(new Teacher("李芳芳",24));    //向上转型
                printDesc(new Student("小明","初1-6班"));//向上转型  
          }
    }

    运行打印:

     

    从上面代码可以看到, 我们直接通过Object参数,便兼容了不同类的一致性

     

    5.覆写equals()

     

    覆写equals()的意义和toString()类似,主要是方便程序设计,并且通过equals()可以判断对象是否相同.

    覆写equals()时,则需要判断的有:

    • 两个对象地址是否相同
    • 对象是否为NULL
    • 两个对象是否为相同类
    • 两个对象的内容是否一致...
    class Student
    {
        String name;        //名字
        String clas;        //班级    
        int score;          //成绩
        
        Student(String name,String clas,int score)
        {
            this.name = name;
            this.clas = clas;
            this.score = score;
        }
    /*覆写Object类的equals方法*/
        public boolean equals(Object obj)
        {
            if(obj == null)    //地址为null
                return  false;
            
            if(obj instanceof Student == false)  //非本类
            {
                System.out.println("ERR");
                return false;
            }
            
            if(this == obj)        //地址相同
                return true;
            
            Student st = (Student)obj;
    
            if(this.name.equals(st.name) &&
                this.clas.equals(st.clas) &&
                 this.score == st.score  )
                return true;
    
            return false;
        }
    
    }

     

    6.覆写hashCode()

     

    6.1 Object类中的hashCode()和String类中的hashCode()

    hashCode()用来获取一个对象的哈希值,一般用来比较用的,而 Object类中的hashCode是返回对象在内存中地址转换成的一个int值(实际就是地址值)。所以如果没有重写hashCode方法,任何对象的hashCode都是不相等的。

    而对于String类中的hashCode方法,则根据对象自身的字符串内容来生成一个哈希值

    6.2 参考示例如下所示:

    class Student                    //未覆写hashCode()的类
    {       
             String name;
             String clas;
             Student(String name,String clas)
             {
                      this.name = name;
                      this.clas = clas;
             }
    }
    
    public class Test
    {
             public static void main(String args[]){
                      Student st1 = new Student("小明","初1-6班");
                      Student st2 = new Student("小明","初1-6班");
                      System.out.println("st1:"+st1.hashCode());
                      System.out.println("st2:"+st2.hashCode()); 
    
                      String str1 = new String("小明  初1-6班");
                      String str2 = new String("小明  初1-6班");
                      System.out.println("str1:"+str1.hashCode());
                      System.out.println("str2:"+str1.hashCode());       
             }
    }

    运行打印:

     

    如上图可以看到,对于相同内容st1和st2而言,它们的hash值完全不同,如果我们将它们使用到Hashtable之类的哈希表上的话,将会出现 st1和st2内容相同,却存储在表里的位置却不同,

    并且比较st1和st2相等时,也会出现false.

    因为判断哈希表里两个对象相等时,也会先判断hash值是否相等再判断是否equals().

    目的:hash值能够加快判断速度,但是hash值也有可能值相同从而出现冲突,所以如果两个对象相等时,会再次判断一次equals().

    6.3 接下来重写修改上面类覆写hashCode()

    class Student                   
    {       
             String name;
             String clas;
             Student(String name,String clas)
             {
                      this.name = name;
                      this.clas = clas;
             }
             public int hashCode()              //覆写hashCode()
             {
                      return name.hashCode()*2+clas.hashCode();
             }
    }

    运行打印:

     

    下章学习:12.JAVA-基本数据类型的包装类操作

  • 相关阅读:
    Python3标准库:copy复制对象
    Python3标准库:weakref对象的非永久引用
    Python3标准库:queue线程安全的FIFO实现
    Python3标准库:bisect维护有序列表
    Python3标准库:struct二进制数据结构
    Python3标准库:heapq堆排序算法
    Python3标准库:array数组
    Python3标准库:collections容器数据类型
    20-如何运行容器?
    19-Docker 镜像小结
  • 原文地址:https://www.cnblogs.com/lifexy/p/10845739.html
Copyright © 2020-2023  润新知