zoukankan      html  css  js  c++  java
  • Java基础之Object类

    类Object是类层次结构的根类。每个类都直接或者间接地继承Object类。所有对象(包括数组)都实现这个类的方法。Object类中的构造方法只有一个,并且是无参构造方法,这说明每个类中默认的无参构造方法调用的就是Object类的无参构造方法。

    1、hashCode方法

    hashCode方法返回给调用者此对象的哈希码(其值由一个hash函数计算得来,一般是通过将该对象的内部地址转换成一个整数)。这个方法通常用在基于hash的集合类中(像java.util.HashMap,java.until.HashSet和java.util.Hashtable)以提高性能。

    1 @Test
    2 public void testHashCode() {
    3     Student student = new Student();
    4 
    5     for (int i = 0; i < 3; i++) {
    6         System.out.println(student.hashCode());
    7     }
    8 }
    1 249123537
    2 249123537
    3 249123537

    我们可以看到运行了3次(Student类在文章最后),结果是一样的,Java中对hashCode方法有如下约定:

    1. 在Java应用程序执行期间,在对同一对象多次调用hashCode方法时,必须一致地返回相同的整数,前提是将对象进行equals比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
    2. 如果根据equals(Object)方法,两个对象是相等的,那么对这两个对象中的每个对象调用hashCode方法都必须生成相同的整数结果。
    3. 如果根据equals(java.lang.Object)方法,两个对象不相等,那么对这两个对象中的任一对象上调用hashCode方法不要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

    上面3句话可以理解为:

    两个对象相等 <=> equals相等  => hashCode相等

    hasCode不相等 => equals不相等 <=> 两个对象不相等

    说来说去还是不知道这个hasCode方法是用来做什么的,上面提到该方法通常用在基于hash的集合类中,以提高性能,以Set集合为例,当往集合中添加一个新的对象时,需要知道在当前集合中是否存在存在该对象,Java会先调用hasCode方法判断集合中是否有对象的哈希码值与新的对象相等,如果不相等,则添加,如果相等,则继续用equals方法判断2个对象是否相等,只有当哈希码相等时,并且equals方法返回为true时,2个对象才认为是相等的。

    2、equals方法

    该方法可以用来检查一个对象与调用这个equals()的这个对象是否相等。equals字面意思是相等,说到相等,我们想到==这个运算符也是用来比较相等的,那么这两个有什么区别呢,当==用于基本类型时比较的是基本类型的值是否相同,用于引用类型时,比较的是引用类型的地址是否指向同一个地方,Object中的equals方法与==运算符是一样的

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

    既然有了==运算符,那还需要equals方法做什么呢,通常情况下,比较2个两个对象的地址值意义不大,所以需要重写Object类中的equals方法来满足自己的需求,例如String类中的equals方法表示的是字符串的内容是否相等。

     1 public boolean equals(Object anObject) {
     2     if (this == anObject) {
     3         return true;
     4     }
     5     if (anObject instanceof String) {
     6         String anotherString = (String) anObject;
     7         int n = value.length;
     8         if (n == anotherString.value.length) {
     9             char v1[] = value;
    10             char v2[] = anotherString.value;
    11             int i = 0;
    12             while (n-- != 0) {
    13                 if (v1[i] != v2[i])
    14                         return false;
    15                 i++;
    16             }
    17             return true;
    18         }
    19     }
    20     return false;
    21 }

    如果重写了equals方法,则hashCode也有必要重写。

    3、getClass方法

    返回此 Object 的运行时类(类对象),我们知道类是对具有一组相同特征或行为的实例的抽象并进行描述,对象则是此类所描述的特征或行为的具体实例。作为类,其本身也具有某些共同的特性,如都具有类名称、由类加载器去加载,都具有包,具有父类,属性和方法等。在Java中用Class这个类来表示其他类所具有的这些特征,因此,类本身也都是属于Class类的对象。为了与平时所说的对象区分开,通常情况称之为类对象。

    1 @Test
    2 public void testGetClass() {
    3     Student student = new Student();
    4     System.out.println(student.getClass());
    5 }
    class com.java.test.Student

    4、toString方法

    返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。我们看Object类中的toString方法

    1 public String toString() {
    2     return getClass().getName() + "@" + Integer.toHexString(hashCode());
    3 }

    当我们使用System.out.println(object)时,内部也是通过调用toString()来实现的。

    1 @Test
    2 public void testToString() {
    3     Student student = new Student();
    4     System.out.println(student);
    5     System.out.println(student.toString());
    6     System.out.println(student.getClass().getName() + "@" + Integer.toHexString(student.hashCode()));
    7 }
    1 com.java.test.Student@cb5efc8
    2 com.java.test.Student@cb5efc8
    3 com.java.test.Student@cb5efc8

    由于这个信息一般没有什么太大作用,所以建议所有子类都重写此方法。 重写了Student类中的toString方法后

    1 Student [name=null, age=0]
    2 Student [name=null, age=0]

    这时候的信息我们就可以很容易的理解了。

    5、clone方法

    创建并返回此对象的一个副本。副本可以这么理解,原来有一个文档,通过Ctrl+C复制,然后Ctrl+V黏贴一个新的文档出来,这个新的文档就叫做文档的副本,你在副本上面所做的操作不会影响到原来的文档。注意在调用clone()方法时,被调用对象需要实现Cloneable接口,如果没有实现Cloneable接口,并且子类直接调用Object类的clone()方法,则会抛出CloneNotSupportedException异常。Cloneable接口是标记接口,接口本身不包含任何方法,表示实现了这个接口,就可以实现对象的复制了。

     1 @Test
     2 public void testClone() throws CloneNotSupportedException {
     3     Student student1 = new Student("John", 23);
     4     Student student2 = (Student) student1.clone();
     5     System.out.println(student1);
     6     System.out.println(student2);
     7     System.out.println("改变student1的属性值后:");
     8     student1.setName("Jack");
     9     student1.setAge(22);
    10     System.out.println(student1);
    11     System.out.println(student2);
    12 }
    1 Student [name=John, age=23]
    2 Student [name=John, age=23]
    3 改变student1的属性值后:
    4 Student [name=Jack, age=22]
    5 Student [name=John, age=23]

    从运行结果也可以看出,被调用对象student1更改了属性值后,不会影响到副本的属性值,也说明了两者在堆空间中的位置不同。

    6、finalize方法

    1 protected void finalize() throws Throwable { }

    当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。通常情况下,这个方法一般不会用到。

    附完整代码:

     1 package com.java.test;
     2 
     3 import org.junit.Test;
     4 
     5 public class StudentTest {
     6 
     7     @Test
     8     public void testHashCode() {
     9         Student student = new Student();
    10 
    11         for (int i = 0; i < 3; i++) {
    12             System.out.println(student.hashCode());
    13         }
    14     }
    15 
    16     @Test
    17     public void testGetClass() {
    18         Student student = new Student();
    19         System.out.println(student.getClass());
    20     }
    21 
    22     @Test
    23     public void testToString() {
    24         Student student = new Student();
    25         System.out.println(student);
    26         System.out.println(student.toString());
    27         System.out.println(student.getClass().getName() + "@" + Integer.toHexString(student.hashCode()));
    28     }
    29 
    30     @Test
    31     public void testClone() throws CloneNotSupportedException {
    32         Student student1 = new Student("John", 23);
    33         Student student2 = (Student) student1.clone();
    34         System.out.println(student1);
    35         System.out.println(student2);
    36         System.out.println("改变student1的属性值后:");
    37         student1.setName("Jack");
    38         student1.setAge(22);
    39         System.out.println(student1);
    40         System.out.println(student2);
    41     }
    42 }
     1 package com.java.test;
     2 
     3 public class Student implements Cloneable {
     4     private String name;
     5     private int age;
     6 
     7     public Student() {
     8         super();
     9     }
    10 
    11     public Student(String name, int age) {
    12         super();
    13         this.name = name;
    14         this.age = age;
    15     }
    16 
    17     public String getName() {
    18         return name;
    19     }
    20 
    21     public void setName(String name) {
    22         this.name = name;
    23     }
    24 
    25     public int getAge() {
    26         return age;
    27     }
    28 
    29     public void setAge(int age) {
    30         this.age = age;
    31     }
    32 
    33     @Override
    34     public String toString() {
    35         return "Student [name=" + name + ", age=" + age + "]";
    36     }
    37 
    38     @Override
    39     protected Object clone() throws CloneNotSupportedException {
    40         return super.clone();
    41     }
    42 
    43 }
  • 相关阅读:
    Idea中配置tomcat启动maven项目读取指定的profile文件
    idea下将springboot项目打成war包发布到本地tomcat服务器上
    NameNode多目录配置
    Android 集成百度ocr报错[283506] Load jni so library error
    Android 集成科大讯飞语音识别(语音听写)报错‘创建对象失败,请确认libmsc.so放置正确,且有调用createUtility进行初始化’
    Android 集成百度地图,定位,导航,围栏,禁区功能
    Android 加载本地图片失败的问题
    Android 闪光灯测心率
    剑指offer(一)
    腾讯云重启慢
  • 原文地址:https://www.cnblogs.com/huangminwen/p/5990325.html
Copyright © 2011-2022 走看看