JavaSE - 调用和重写Object类中的toString方法、equals方法以及理解Arrays类中的toString方法

发布于:2023-01-14 ⋅ 阅读:(576) ⋅ 点赞:(0)

目录

1. 类型和类

2. Object类

2.1 定义在Object类中的方法:

3. 调用Object类中的toString方法以及重写toString方法

3.1 println 输出 与 toString方法的调用和重写

总结:(!!!)

3.2 数组与Arrays类中的toString方法与Object类中的toString方法的调用和重写

3.2.1 如何输出数组中的元素呢?

3.2.2 若数组中的每个元素都是引用数据类型的,如何输出数组中的每个元素呢?

4. 调用Object类中的equals方法以及重写equals方法

4.1  == 与 Object类中equals方法的区别

4.2 调用Object类中的equals方法以及重写equals方法

5. 总结:(!!!)


1. 类型和类

基本数据类型:byte,short,int,long,float,double,boolean,char 

除了这八种基本数据类型以外,其余都是引用数据类型,包括数组这个对象,也是引用数据类型。

类型包括基本数据类型和引用数据类型。

类就是自定义类型,就是引用数据类型。

总结:类和类型是不一样的,类型包括基本数据类型和引用数据类型,类就是引用数据类型。

2. Object类

Object类是所有类的父类。

当一个类被定义后,如果没有指定继承的父类,那么默认继承Object类。

形参是Object类型时,可以接收所有引用数据类型的实参。

观察下面代码,为什么一个可以运行,一个会报错?

因为Object类是所有类的父类,所以形参是Object类型时,可以接收所有引用数据类型的实参,传参时会发生向上转型。数组是引用数据类型的,所以可以成功传参。

但是因为Object类是引用数据类型基本数据类型不能直接传参给引用数据类型,要通过它的包装去传。而int是基本数据类型,所以会报错。

2.1 定义在Object类中的方法:

3. 调用Object类中的toString方法以及重写toString方法

3.1 println 输出 与 toString方法的调用和重写

基本数据类型的变量存的是变量的值引用数据类型的变量存的是对象的地址

我们知道打印基本数据类型的变量的话,输出的是变量的值,那么打印引用数据类型的变量,输出的是什么呢?

如下:

果然,(3)输出了age中的值

观察(1),输出的这一串是个什么东西,是地址吗?

我们去看一下println的源码

让我们再去看看valueOf方法的源码

  • 可能会有疑问,为什么在没有对Object进行实例化的情况下,obj.String可以成功调用Object类中的toString方法?不是要先实例化才能调用吗?
  • 因为Object类是所有类的父类,和String类构成父子关系,所以在子类中调用父类中的非静态构造方法,通常先对子类进行实例化,然后通过【子类类型的引用.方法】调用,此时形参Object obj接收的是子类类型的引用,传参时会发生向上转型,被obj成功接收,obj本质上就是引用,之前已经实例化过了,所以,obj.toString可以成功调用toString方法。

解释清楚这些,下面让我们去看看toString方法的源码吧

 

没错,当我们打印引用数据类型时,会调用Object类中的toString方法,此方法返回的是String类型的数据:类名+@+哈希值的16进制形式 ,于是就会输出那一串东西啦,我们可以简单的认为那一串东西就是“地址”。

现在我们去观察(2),咦,person.name 是String类型的变量,String也是引用数据类型,为什么输出的是值不是“地址”呢?怎么输出了字符串?

原来在String类中重写了toString方法,当我们打印引用数据类型时,调用的是子类中重写的toString方法,而String类中重写的toString方法返回的是字符串本身,于是就不会输出“地址”,直接输出字符串啦。

总结:(!!!)

当我们打印基本数据类型的变量时,输出的是变量的值,

当我们打印引用数据类型的变量,会调用toString方法,

  • 如果子类中没有重写toString方法,输出的是“地址”;
  • 如果子类中重写了toString方法,根据重写的toString方法确定输出什么。

于是,我们就可以通过在自己的类中重写toString方法,来实现对对象内容的打印,而不是输出对象的“地址”。

如下,在子类中重写toString方法,输出对象的内容。

public class Test {
    private String name = "zhangsan";
    private int age = 18;
 
    @Override
    public String toString() {
        return name + " " +age ;
 
    }
 
    public static void main(String[] args) {
        Test test = new Test();
 
        System.out.println(test);
    }
 
 
}

3.2 数组Arrays类中的toString方法Object类中的toString方法的调用和重写

3.2.1 如何输出数组中的元素呢?

我们知道数组是引用数据类型的,那通过调用Object类中的toString方法,输出的只能是“地址”

想要输出数组中的元素,有两种解决方法:

方法一:重写Object类中的toString方法,使它返回数组中的每个元素,发现我并不会写。额。好吧,只能采用第二种方法了。

方法二:直接使用数组的工具类Arrays,调用工具类Arrays中的toString方法,此方法的作用就是:输出数组中的所有元素。

如下:

Arrays类中的toString方法为什么会输出数组中的元素呢? 

让我们来看看它的源码:

于是,调用Arrays类中的toString方法,就输出了数组中的元素。 

注意:Arrays类中的toString方法和Object类中的toString方法没有任何联系,只是方法名重名而已,Arrays类中的toString方法是有参数的,Object类中的toString方法是无参的

对比图如下:

3.2.2 若数组中的每个元素都是引用数据类型的,如何输出数组中的每个元素呢?

 

发现确实将数组中的每个元素打印出来了,但是为什么打印出来的是"地址"?

难道是在此过程中会调用Object类中的toString方法,而我们没有重写toString方法吗?

让我们去看一下Arrays类中toString方法的源码:

让我们去看看String类中的toString方法:

没错,又调用了Object类中的toString方法

于是,当我们调用Arrays中的toString方法区打印引用数据类型的每个元素时,每个元素都会先调用Object类中的toString方法,变成“地址”,然后再被打印出来,循环执行这个两个动作。所以我们会看到输出的都是“地址”。

分析到这里,我们自然而然就想到了解决办法,那就是重写Object类中的toString方法:

让每个元素去调用的toString方法不在返回“地址”,而是返回它指向的对象。

代码如下:

import java.util.Arrays;

class People{
    public String name;
    public int age;

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

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class TestDemo {
    public static void main(String[] args) {
        People[] p = {
                new People("zhangsan",18),
                new People("lisi",20)
        };
        System.out.println(Arrays.toString(p));

    }
}

嘿嘿,成功啦! 

4. 调用Object类中的equals方法以及重写equals方法

4.1  == 与 Object类中equals方法的区别

在Java中,对于 == 来说:

如果比较的是基本数据类型变量,比较的是变量中值是否相同(不一定数据类型相同)
如果比较的是引用数据类型变量,比较的是引用变量里面存储的地址是否相同。

那么Object类中的equals方法比较的是什么呢?

先来看一下Object类中的equals方法的源码:

观察发现,形参是Object类型的,即引用数据类型的,所以只能接收引用数据类型的实参。

又因为,对于==来说,如果比较的是引用数据类型变量,比较的是引用变量里面存储的地址是否相同。

所以调用Object类中的equals方法,比较的是变量里存的地址是否相同。且只能比较引用数据类型的变量。

4.2 调用Object类中的equals方法以及重写equals方法

观察(1),比较的是基本数据类型(int)的变量,只能用==来比较是否相等。

比较的是变量中的值。

观察(2),比较的是引用数据类型(int[])的变量,可以使用==和equals方法来比较是否相等。

且比较的都是变量中存的地址是否相等。存的地址是不同的,所以输出false

观察(3),比较的是引用数据类型(String)的变量,可以使用==和equals方法来比较是否相等。

咦?我们发现输出的结果是不同的,如果调用的是Object类中的equals方法,那么==和equals方法比较的都是变量中存的地址是否相等,那么输出结果应该是相同的呀,为什么会一个输出false,一个输出true呢?

原来,String类中重写了equals方法,所以调用equals方法时,会调用子类重写的equals方法,而重写的equals方法比较的是字符串是否相等。所以会输出true。

5. 总结:(!!!)

1. 类型和类的区别:类型包含基本数据类型和引用数据类型,类就是引用数据类型。引用数据类型的形参只能接收引用数据类型的实参,不能接收基本数据类型的实参。

2. Object类中的toString方法和equals方法调用前,最好都要先重写再使用。

3. 输出数组中的元素,使用数组工具类Arrays类中的toString方法

4. 对于引用数据类型的变量println输出时会调用Object类中的toString方法。若数组中的每个元素都是引用数据类型的,每个元素在被打印前都会先调用Object类中的toString方法,然后再被打印。所以对于这两种情况,一定不要忘记重写了。否则,输出的就是“地址”。

5. == 与 Object类中equals方法的区别:==可以比较基本数据类型的变量是否相等,也可以比较引用数据类型的变量是否相等,但是equals只能比较引用数据类型的变量是否相等,当比较的是引用数据类型的变量时,==和equals比较的都是变量中存的地址。对于equals来说,要想比较变量指向的对象,要重写equals。

6. 对于String类的字符串来说,String类中会重写toString方法和equals方法,所以当调用这两个方法时,不会去调用Object类中的,会调用String类中自己重写的。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到