目录
二. 使用数组工具类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方法!!!