前言

我们在进行 Java 编程时,经常要打印对象,有的是查看是否拿到了该对象,有的是查看该对象中的数据。打印输出的却是一知半解的字符串,那么这个字符串是怎么来的?代表什么?我们如何打印出对象中的数据呢?

一、Java中打印对象

1.演示代码

我们使用 Java 的 System.out 类可以打印输出对象,例如我们有一个 Student 类,有三个成员变量,一个有参构造方法,它的代码如下:

public class Student {

    private String name;
private String sex;
private Integer age; public Student(String name, String sex, Integer age) {
this.name = name;
this.sex = sex;
this.age = age;
}
}

然后我们新建测试类,创建 Student 对象,并直接使用 System.out.println 语句进行打印。

public class Test {
public static void main(String[] args) {
Student student = new Student("张三", "男", 16);
System.out.println(student);
}
}

执行结果如下:

com.example.Student@2f4d3709

2.提出问题

通过演示代码运行结果可以看到打印输出的是当前包下的类名,还有@字符,还有一串数字和字母。打印出类名很好理解,但是@、数字、字母是什么意思呀?应该很多同学都不是很明白吧。

二、深入分析

1.打印的字符串是什么

当我们在 Java 中使用 System.out.println 或者其他输出语句时,如果传入的参数不是字符串类型的数据,那么程序会自动调用该数据所属类的 toString() 方法。目前 Student 类中并没有 toString() 方法呀,是所有 Java 类都直接或间接继承了 Object 类,而 Object 类中有一个默认的 toString() 方法,代码如下:

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

该方法官方注释如下:

该方法返回对象的字符串表示形式。一般来说,toString 方法返回一个“文本表示”此对象的字符串。结果应该是一个简洁但信息丰富的表示,便于人们阅读。建议所有子类重写此方法。

Object 类的 toString 方法返回一个字符串,该字符串由该对象作为其实例的类的名称、@符号字符’ @'以及该对象哈希码的无符号十六进制表示形式组成。换句话说,这个方法返回的字符串等于的值:getClass().getName() + ‘@’ + Integer.toHexString(hashCode())

也就是我们的 Student 没有重写 toString() 方法,而是自动调用了 Object 类中的 toString() 方法。这时候我们打印输出的是一个字符串,其中包含对象的类名和哈希码。

2.是对象的地址吗?

有时候我们总是说打印了该对象的地址,其实是不准确的。打印的内容一个是类名,一个是哈希码。打印的对象的哈希码并不是引用地址,尽管在某些情况下它们可能看起来像是一样的。

哈希码是一个整数,它是由 Java 运行时环境根据对象的内部状态计算出来的。对于一个类的任何两个不同的实例,它们的哈希码通常不会相同。也就是说,如果在打印一个对象时,看到了两个不同的哈希码,可以确定这两个对象是不同的,它们占用不同的内存空间。

而引用地址是内存中的一个地址值,它表示某个对象在内存中的位置。对于同一个对象,无论它被引用多少次,它的引用地址始终是相同的。两个不同的对象的引用地址也是不同的。

通常情况下,打印一个 Java 对象时显示的是该对象的字符串表示,这个字符串既包括了实例的哈希码,也包括了它的一些其他信息。因此,在某些情况下,打印出来的哈希码和引用地址可能看起来相同,但实际上它们是不同的概念。

三、打印对象内部信息

如何打印对象内部信息呢,比如打印出对象中姓名、性别和年龄。这时需要我们自定义或是重写 Student 类的 toString() 方法。如下代码中我们重写 toString() 方法:

public class Student {
private String name;
private String sex;
private Integer age; public Student(String name, String sex, Integer age) {
this.name = name;
this.sex = sex;
this.age = age;
} @Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
'}';
}
}

我们再次执行 Test 中的 main() 方法,可得结果如下:

Student{name='张三', sex='男', age=16}

这时就调用了被重写的 toString() 方法,并按照我们的意愿对 student 对象进行了打印输出。

总结

这里我们知道了 Java 中打印对象,如果没有重写 toString() 方法,那么调用执行的是 Object 类中的 toString() 方法,会打印该对象的类名和哈希码,而它的哈希码也不是对象的地址。如果想更好的输出对象信息,可以重写 toString() 方法。


关注公众号:编程火箭车

我们定期发布编程相关的文章、资讯、活动等内容。帮助编程爱好者、初学者或初级程序员快速入门、打牢基础。欢迎大家关注,和我们一起探索编程的精彩世界

Java中打印对象输出的字符串到底是什么?的更多相关文章

  1. java中直接打印对象

    java中直接打印对象,会调用对象.toString()方法.如果没有重写toString()方法会输出"类名+@+hasCode"值,hasCode是一个十六进制数 //没有重写 ...

  2. Java中String对象的不可变性

    首先看一个程序 package reverse; public class Reverse { public static void main(String[] args) { String c1=n ...

  3. Java中计算对象的大小

    一.计算对象大小的方法 Java中如何计算对象的大小呢,找到了4种方法: 1.java.lang.instrument.Instrumentation的getObjectSize方法: 2.BTrac ...

  4. 【学习笔记】Java中生成对象的5中方法

    概述:本文介绍以下java五种创建对象的方式: 1.用new语句创建对象,这是最常用的创建对象的方式. 2.使用Class类的newInstance方法 3.运用反射手段,调用java.lang.re ...

  5. JAVA中JavaBean对象之间属性拷贝的方法

    JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,对于这种情况,可以采用以下几个简便方法处理. 下面对这 ...

  6. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  7. 【译】Java中的对象序列化

    前言 好久没翻译simple java了,睡前来一篇. 译文链接: http://www.programcreek.com/2014/01/java-serialization/ 什么是对象序列化 在 ...

  8. JAVA中JavaBean对象之间拷贝的方法

    JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,有个更简便的方法,他们之间的拷贝可以通过copyPro ...

  9. Java中的对象池技术

    java中的对象池技术,是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果池中没有则创建一个),则在需要重复重复创建相等变量时节省了很多时间.对象池其实也就是一个内存 ...

  10. Java中Date()类 日期转字符串、字符串转日期的问题(已解决)

    Java中Date()类 日期转字符串.字符串转日期的问题 今天在写东西的时候突然发现一个问题,就是先new 一个Date()然后将生成的值转为字符串, 然后再将转换后的字符串再次用new Date( ...

随机推荐

  1. MapReduce Shuffle源码解读

    MapReduce Shuffle源码解读 相信很多小伙伴都背过shuffle的八股文,但一直不是很理解shuffle的过程,这次我通过源码来解读下shuffle过程,加深对shuffle的理解,但是 ...

  2. 《HelloGitHub》第 84 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweiha ...

  3. 在ArcGIS Pro中对Revit的bim数据进行地理配准(平移、旋转等)

    在ArcGIS Pro中,打开Revit的rvt格式数据,默认是没有坐标系,且位置会放置在原点位置(0,0),在实际使用过程中,需要对rvt数据进行地理配准,包括平移.旋转等操作将bim数据放置在正确 ...

  4. 动态开点线段树&线段树合并学习笔记

    动态开点线段树 使用场景 \(4 \times n\) 开不下. 值域需要平移(有负数). 什么时候开点 显然,访问的节点不存在时(只会在修改递归时开点). trick 区间里面有负数时,\(mid ...

  5. [VMware/CENOTS/Linux]VMware设置CentOS7共享文件夹[转载]

    0 环境信息 VMWare: Linux CENTOS: 7.9.2009(Core) CPU: x86_64 / amd64 待共享的共享文件夹的物理路径: E:\VirtualMachine\sh ...

  6. arc076f F - Exhausted?

    ARC076 F - Exhausted? [题目大意] \(有m个座位,分别位于坐标为1,2,3,...,m的地方:n个客人,第i位客人只坐位于[0,li]∪[ri,m]的座位.每个座位只能坐一个人 ...

  7. 随机模块random os模块 序列化模块

    random: 验证码的实现: choice是选择列表中任意一个 ##记得把randint取出来的数字转化成str类型,要不就会相加 ##cha()是把asc编码表里的数字转化成字符 更进一步做成函数 ...

  8. Java Heap

    堆 堆是一种基于树的数据结构,是一种完全二叉树,堆中的所有的节点都按照特定的顺序排列. 在堆数据结构中,如果任意父节点的值都大于其子节点,则会产生一个大顶堆:反之,如果任意父节点的值都小于其子节点,则 ...

  9. Intellij_idea for循环 快捷键

    for循环四次.用 i 进行for循环 4.for fori 增强for循环 int [] arrays=new int[2]; arrays.for

  10. Android 为什么事件分发的入口函数是dispatchTouchEvent

    参考:https://xiaozhuanlan.com/topic/8946537021 从触摸屏幕到事件在底层传输最终会到: private int processPointerEvent(Queu ...