案例演示
// 首先我们利用小案例来引出问题
// 实例化 Object 对象
Object o = new Object();
// java.lang.Object@6d03e736
System.out.println(o.toString());
// 实例化 Teacher对象 ⇒ 当前 Teacher 类没有继承 Object 类
Teacher teacher = new Teacher();
//OOP.Day2.API_2.Teacher@378bf509
System.out.println(teacher.toString());
//OOP.Day2.API_2.Teacher@378bf509
System.out.println(teacher);
我们会发现 使用
teacher
对象名调用Object
类的toString()
方法是可以的.
这表示当前Teacher
类如果没有继承其他类,会默认继承Object
类
查看Object
类源码
public Object() {}
Object
类就只有一个" 公开的无参构造方法"- 当子类实例化时,是通过
new + 类名()
进行实例化- 其中:
new
关键字是实例化的重要特征 类名()
表示调用当前类的无参构造方法- 那么子类在创建对象是 会通过
new
关键字 默认 使用父类的无参构造方法, 那么这个时候 子类可以使用父类的非私有化成员变量和成员方法
- 其中:
问题引入
那么为什么直接打印对象名 和 直接打印对象调用父类
toString()
的结果是相同的呢
这个时候需要深入了解System.out.println()
打印方法
我们分解一下: System.out.println();
System:类名
out : 静态变量
System.out : 表示获取打印的对象
- 可以看下面这张图
接着我们在看一下print()
方法 中的源码:
// 它具有多种重载形式 ⇒ 当我们传入一个 Object 类型时
public void println(Object x) {
// 将当前Object类型存储的数据转换为字符串的形式存储
String s = String.valueOf(x);
// 通过判断来打印当前字符串信息
if (getClass() == PrintStream.class) {
// need to apply String.valueOf again since first invocation
// might return null
writeln(String.valueOf(s));
} else {
synchronized (this) {
print(s);
newLine();
}
}
}
这里有涉及到几个方法
一个
writeln()
方法
此时我们进入writeln()
源码中查看
private void writeln(String s) {
try {
synchronized (this) {
ensureOpen();
// 对当前字符串进行打印
textOut.write(s);
// 进行换行处理
textOut.newLine();
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush)
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
一个
valueOf()
方法
此时我们进入valueOf()
源码中查看
// 我们不难发现它是默认调用的Object类的toString()方法
public static String valueOf(Object obj) {
// 如果当前obj中内容为空返回 字符串 null 否则返回 obj.toString()
return (obj == null) ? "null" : obj.toString();
}
一个
toString()
方法
此时我们进入toString()
源码中查看
// 不难看出 他是使用反射 获取当前类的完成包名 和方法获取当前内存地址的16进制表示
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
总结
当我们打印一个对象的时候,底层会调用对象的
toString
方法,把对象变成字符串。
然后再打印在控制台上,打印完毕换行处理。