JavaSE - System.out.println 输出的是什么、关于toString方法的那些事儿

目录

一. System.out.println 输出的 是什么

总结:(!!!)

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

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

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

总结:(!!!)

最后


一. System.out.println 输出的 是什么

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

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

如下:

果然,(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方法,输出对象的内容。

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);
    }
 
 
}


总结:(!!!)

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

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

如果子类中没有重写toString方法,输出的是“地址”,

如果子类中重写了toString方法,根据重写的toString方法确定输出什么。

3. 所以,我们可以通过重写toString方法,来自己决定println输出的什么(是引用类型时),

而且一般情况下,只要使用System.out.println打印引用类型的变量,我们一定不要忘记重写toString方法,因为输出地址没啥用。

4. 特别的,String这个类中,自己重写了toString方法,所以输出的才会是字符串,不是地址。

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

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

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

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

方法一:重写Object类中的toString方法,使它返回数组中的每个元素。

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

如下:

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

让我们来看看它的源码:

于是,调用Arrays类中的toString方法,再通过println就输出了数组中的元素(输出的其实是个元素拼接成的字符串) 

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

对比图如下:

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

 

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

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

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

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

于是,当数组中的每个元素是引用数据类型时,调用Arrays中的toString方法,每个元素都会先调用Object类中的toString方法,变成“地址”,然后拼接成字符串被println打印出来,所以我们会看到输出的都是“地址”。

分析到这里,我们自然而然就想到了解决办法,那就是重写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));

    }
}

嘿嘿,成功啦! 


总结:(!!!)

1. Arrays类中的toString方法Object类中的toString方法没有一点联系,只是名字一样而已,本质上是两个不同的方法。 

2. 我们使用数组工具类Arrays中的toString方法结合println输出数组中的每个元素

如果数组中的元素是基本数据类型输出的就是每个元素(拼接成的字符串

如果数组中的元素是引用数据类型输出的会是“地址”组成的字符串。是因为中间又调用了Object中的toString方法。

3. 所以,当数组中的每个元素是引用数据类型的时候,一定不要忘记重写toString方法

4. 特别的,当数组中的每个元素是String类型时,String类中自己重写了toString方法,所以不会输出“地址”组成的字符串,会正常输出数组中每个元素。


最后

除了已经重写toString方法String类以外,

使用System.out.println输出引用数据类型变量时,

数组中每个元素都是引用数据类型,使用Arrays.toString()时

一定一定一定不要忘记重写toString方法!!!

  • 24
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
public void initalCourse() { File file = new File("course.bat"); /** 判断这个文件或者目录是否存在,默认是true存在的,如果不存在则为false */ if (!file.exists()) { List<Course> list = new ArrayList<>(); //创建课程对象 Course course1 = new Course(1001, "初始化HTML5", "前端开发", 30, "30小时", "teacherZhang"); Course course2 = new Course(1002, "HTML5+CSS3", "前端开发", 40, "40小时", "teacherZhang"); Course course3 = new Course(1003, "javaSE入门", "后端开发", 40, "90小时", "lisi"); Course course4 = new Course(1004, "MYSQL数据库", "后端开发", 50, "50小时", "zhangsan"); //将所有课程添加到集合中 list.add(course1); list.add(course2); list.add(course3); list.add(course4); //将集合添加到文件中 saveCourse(list); } } /** 查询全部课程的信息 */ private void showAllCourse() { //调用显示全部的课程的方法 if (role != null) { List<Course> query = role.query(); showList(query); } } private void showList(List<Course> list){ System.out.println("课程编号\t课程名称\t\t课程类别\t\t总课时\t总时长\t主讲老师"); for (Course course:list) { System.out.println(course);//调用了Course默认的toString } } public List<Course> query() { if (teaAuthority == null) { System.out.println("对不起,您还没有登录,请先登录再去操作数据"); } else { return teaAuthority.getAllCourse(); } return null; } 这里for (Course course:list) {报错Exception in thread "main" java.lang.NullPointerException at com.sxau.learningsystem.service.impl.SuperServiceImpl.showList(SuperServiceImpl.java:255)
07-12

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值