Object类

相信有一双善于观察的眼睛的你一定发现了,我们每次使用对象去.的时候,总是会有很多我们自己没有写过的方法。

就像这些:

我们明明没有写这些,为什么会有呢?这就必须得提到我们的类的鼻祖:Object类了。

1.Object是什么?

所有的类都直接或者间接的继承了Object类。如果该类继承了除Object类的其它类,则该类为间接的继承Object类,若没有继承其它类,则为直接的继承Object类,可以省略extends Object,也可以写上。

那我怎么知道这些方法是干嘛的呀!又不是我写的。

这个时候就需要我们的api帮助文档出场了,里面详细的记载了Object类的所有内容,包括所有方法的含义和使用等等。

2.api的使用

api是Application Programming Interface的缩写,即应用程序编程接口。而api文档,,就像是说明书,里面包含了Java已经定义好的类、接口、抽象类的详细内容。

今后的学习几乎都是参考api文档去学习api里面的类、接口、抽象类的内容。

首先我们需要按照索引来搜索我们想要查询的内容:

输入内容之后按回车:

但是可能有多个,因为有的是类,有的是接口(后续内容会讲)

我们找到Object类:(可以先点击进去,不是就再搜索一次点击另外一个)

可以看到关于这个类有特别详细的解释,往下滑有关于方法的特别详细的解释,(小tip:点击蓝色的方法名就能直接跳转),所以api文档是我们需要好好利用的一个工具。

api百度网盘链接

链接:https://pan.baidu.com/s/1t_cKercpOW3uWReREcf8ug
提取码:p8yj

有需要自取~

3.Object常用方法

所有的类都拥有Object类的所有方法。

以下几个方法必须掌握!

(1)hashcode()

//返回对象的哈希码值
public int hashCode()

hashcode()用于返回对象的哈希码值。哈希码值是对象在内存中的逻辑地址,是相对于真实地址经过一定的运算得到的一个整数,对象的引用地址存储在栈中,真实的值存放在堆中,栈中的引用地址指向堆中的值。

例:

package com.dh.object;

public class HashcodeDemo {

    public static void main(String[] args) {

        //实例化一个对象
        HashcodeDemo hashcodeDemo = new HashcodeDemo();
        //得到对象的哈希码值
        int hashCode = hashcodeDemo.hashCode();
        //输出该对象的哈希码值
        System.out.println(hashCode);

        //每个对象的哈希码值是不一样的
        HashcodeDemo hashcode2 = new HashcodeDemo();
        System.out.println(hashcode2.hashCode());
    }
}

结果:每个对象的哈希码值一般来讲是不一样的

既然我们继承了Object类,那我们也能重写其方法。

如果要让某个类的所有对象都返回相同的值,只需要重写hashcode():

原本调用的是父类的hashcode()

@Override
public int hashCode() {
    return super.hashCode();
}

重写:让hashcode()的返回值为固定的数,则每一个对象都会返回这个值,就会让每个对象hashcode()结果都相同。

package com.dh.object;

public class HashcodeDemo {

    @Override
    public int hashCode() {
        return 1000;    //任意int类型整数
    }

    public static void main(String[] args) {

        //实例化一个对象
        HashcodeDemo hashcodeDemo = new HashcodeDemo();
        //得到对象的哈希码值
        int hashCode = hashcodeDemo.hashCode();
        //输出该对象的哈希码值
        System.out.println(hashCode);

        //实例化新对象,返回其哈希码值
        HashcodeDemo hashcodeDemo2 = new HashcodeDemo();
        System.out.println(hashcodeDemo2.hashCode());
        
        //重写了hashCode()之后,该类的每个对象的哈希码值都一样
        System.out.println(hashcodeDemo.hashCode() == hashcodeDemo2.hashCode());
    }
}

结果:

(2)getClass()

//返回此Object的运行时类
//<>是泛型,后续会讲到,可暂时去掉
public final Class<?> getClass()

首先需要明确的是,Java是强类型语言,严格区分大小写,Class 是一个类型,和我们定义类使用的 class 关键字是不一样的!

在执行Java程序的时候,首先会将.java文件编译成.class字节码文件,如何把字节码文件加载进内存,在Java中,万事万物皆为对象,所以jvm就认为该字节码文件为一个对象,Class类型对应的对象就是:字节码文件(.class)对象。

每个类只有一个.class文件,可想而知,同一个类的实例同属一个.class字节码文件,所以getClass()的值也都是一样的。

例:

package com.dh.object;

public class GetClassDemo {

    public static void main(String[] args) {
        //new一个对象
        GetClassDemo getClassDemo = new GetClassDemo();
        //使用getClass()获得一个Class类型的对象
        Class aClass = getClassDemo.getClass();
        //输出该对象
        System.out.println(aClass);

        //同一个类的实例使用getClass()因返回同一个值
        GetClassDemo getClassDemo2 = new GetClassDemo();
        System.out.println(getClassDemo2.getClass());
    }

}

结果:

getClass()的结果为:class 包名.类名。

getClass()是final修饰的,所以不能被重写。

(3)toString()

//返回对象的字符串表现形式
//返回值为:getClass().getName() + '@' + Integer.toHexString(hashCode())
//可以在IDEA这鼠标放在toString()上,按ctrl,鼠标左键进去看源码,源码例就是这样写的输出
//Integer.toHexString():将十进制转换为十六进制
public String toString()

例:

package com.dh.object;

public class ToStringDemo {

    public static void main(String[] args) {

        //new一个对象
        ToStringDemo toStringDemo = new ToStringDemo();
        //使用toString,返回该对象的字符串表示形式
        String s = toStringDemo.toString();
        //输出该对象的字符串表现形式
        System.out.println(s);

        //不同对象的字符串表现形式
        ToStringDemo toStringDemo2 = new ToStringDemo();
        System.out.println(toStringDemo2.toString());
    }
}

结果:

我们输出对象,看看结果会是什么:

System.out.println("============");
System.out.println(toStringDemo);
System.out.println(toStringDemo2);

观察结果可得:直接输出对象和输出对象的toString()是一样的。

如果输出对象的值为这样的话,就没有什么意义了是不是,这字符串又看不懂,所以我们可以重写一下toString(),用来输出我们想要看到的对象,比如对象的属性。

重写toString():

package com.dh.object;

public class ToStringOverride {

    public String name;
    public int age;

    public ToStringOverride(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    //重写Object的toString()
    public String toString() {
        return "name = "+this.name+"\tage = "+this.age;
    }

    public static void main(String[] args) {

        ToStringOverride toStringOverride = new ToStringOverride("Tom",18);
        //调用重写后的toString()
        String s = toStringOverride.toString();
        System.out.println(s);
    }
}

结果:按照我们的格式输出了数据。

可以看到,只是输出当前的属性,是很简单的操作,但是却要重复的写,强大的IDEA已经给我们提供了快捷方式:alt+ins,选择toString,再选择你要的属性:

@Override
public String toString() {
    return "ToStringOverride{" +
        "name='" + name + '\'' +
        ", age=" + age +
        '}';
}

方便快捷!

(4)equals()

//指示一些其他对象是否等于此。 
public boolean equals(Object obj) 

==和equals()都是用来判断相等的,那它们有什么区别呢?

== 和 equals()的区别
  • ==

    • 基本数据类型:比较的是值

    • 引用数据类型:比较的是内存地址

      package com.dh.object;
      
      public class EqualsDemo {
      
          public static void main(String[] args) {
      
              int a = 1;
              int b = 1;
              
              EqualsDemo equalsDemo1 = new EqualsDemo();
              EqualsDemo equalsDemo2 = new EqualsDemo();
      
              //==比较基本数据类型,比较的是值,值相等,结果为true
              System.out.println(a == b);
              //==比较引用数据类型,比较的是地址,每个对象的地址都不一样,结果为false
              System.out.println(equalsDemo1 == equalsDemo2);
          }
      }
      
      

  • equals()

    • 引用数据类型:比较的是内存地址。(未重写该方法时)

      源码:

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

      equal方法本质上还是==比较。

      在上述代码中,添加使用equals比较的输出语句:

      System.out.println("================");
      System.out.println(equalsDemo1.equals(equalsDemo2));//内存地址不一样,输出false
      

      结果:

    • 字符串:比较的是字符串的内容。(重写了该方法)

String类重写equals()

因为==就可以用来比较两个引用数据类型的地址,如果equals()也是的话,就多余了,所以,我们可以重写equals()方法,让它具有别的功能。String类就已经帮我们实现了这个功能。

String类重写了equals(),用于比较字符串的内容是否相等:

package com.dh.object;

public class EqualsOverride {

    public static void main(String[] args) {

        String s1 = "hello";
        String s2 = "hello";

        System.out.println(s1.equals(s2));
    }
}

我们将鼠标移到equals上,ctrl+鼠标左键点击进入源码:

//实现字符串的值比较(看不懂可暂时不看)
public boolean equals(Object anObject) {
    if (this == anObject) {	
        return true;
    }
    if (anObject instanceof String) {
        String aString = (String)anObject;
        if (coder() == aString.coder()) {
            return isLatin1() ? StringLatin1.equals(value, aString.value)
                : StringUTF16.equals(value, aString.value);
        }
    }
    return false;
}

本人水平有限,若有错误,望指正,感激~

posted @ 2021-01-21 15:35  deng-hui  阅读(274)  评论(0编辑  收藏  举报