为什么System.out.println()中不需要java.io.PrintStream?

为什么System.out.println()中不需要java.io.PrintStream?,java,java-io,Java,Java Io,所以我问自己为什么不必导入java.io.PrintStream来使用System.out。我知道编译器默认导入java.lang。好的 因为System是java.lang的一个类,所以我可以使用System.out字段。但是该字段的类型为java.io.PrintStream,并且默认情况下不会导入该类(它位于java.io包中),因此为什么我可以访问System.out.print(),例如,而不单独导入java.io.PrintStream 如果我创建了我自己的类MyClass,那么我就

所以我问自己为什么不必导入
java.io.PrintStream
来使用
System.out
。我知道编译器默认导入
java.lang
。好的

因为
System
java.lang
的一个类,所以我可以使用
System.out
字段。但是该字段的类型为
java.io.PrintStream
,并且默认情况下不会导入该类(它位于java.io包中),因此为什么我可以访问
System.out.print()
,例如,而不单独导入
java.io.PrintStream

如果我创建了我自己的类
MyClass
,那么我就不能这样做
MyClass-anInstance=newmyclass()MyClass。为什么这不是
打印流所必需的


提前感谢。

如果需要在代码中使用
PrintStream
(类名),则只需导入
PrintStream
。在另一个
PrintStream
类型的对象上使用字段并不需要它

也就是说,
import
是告诉编译器您的代码中的
PrintStream
(文本)是什么意思。这并不是告诉编译器您将使用从其他地方获得的
PrintStream
对象(在本例中为
System

换句话说:
import
就是知道如何编译源文本;这与运行时使用什么无关。例如,导入不会写入类文件;运行时不需要这些信息。字段和变量定义以其完全限定的类名存储,而不是
import
-相对的类名。由于
out
System
中的类型信息表示它是
java.io.PrintStream
,编译器(以及后来的JVM)知道它是
java.io.PrintStream
,无论您是否在代码中导入
PrintStream

X.java

package p;
import q.Y;
public class X { Y y; }
Z.java

import p.X;

... X x = ...;
... x.y ...;
如果出现
X
,编译器需要导入X


对于
x.y
编译器可以在x的类数据中找到具有y等方法的类y。

import语句只是编译器的提示。未使用的导入不会实际链接,并且引用的内容(如
out
)将由编译器链接打印流。
out
不是类,out是
系统中
打印流的实例。仅添加在当前类中使用的类型导入(类/接口/注释)。例如,您可以完全调用某个类中的方法,返回
MyClass
的对象,而不导入。我仍然不明白,sry。是的,out是PrintStream的一个实例,但是PrintStream没有导入,因此结构未知,为什么编译器知道在哪里找到PrintStream等。?结构必须是已知的,否则就没有意义(即调用方法、字段等)。我理解这一点,因此在将这个示例转换为我的案例时,我们可以说java.lang.System导入java.io.PrinterStream?不,该类只包含
PrintStream
的类名和
PrintStream\println的调用签名(字符串)
。JVM/java执行类,然后“链接”总之。这是因为java.lang.System自己导入PrintStream?我现在明白了。谢谢!@TriSo-不,不是真的。
import
是关于知道如何编译源文本。它不是关于在运行时使用什么。所以是的,
System.java
有一个导入
PrintSream
,但编译器k就是这样现在了解编译
System.java
源文本时
PrintStream
中的内容(当他们构建JDK/JRE JAR时)例如,导入不写入类文件;在运行时不需要这些信息。字段和变量以其完全限定的类名存储,而不是导入相对的类名。好的,import语句只针对编译器,以便我可以使用非限定的名称,例如System,而不是java.lang.System。因此,它是有点“重命名”?但我的意思是,编译器从哪里得到PrintStream的定义?它可能更像是一个链接/编译主题?@TriSo-Name Shorting,是的;不是重命名。我只是以一种可能解决这个问题的方式更新了我的答案(在将我上面的评论折叠成答案的过程中)。在编译时,当编译器看到
System.out
时,
java.lang
的默认导入告诉它
System
java.lang.System
,因此它在该类中查找
out
,并看到它是用
java.io.PrintStream
类型声明的。因此它使用该类型来检查成员(方法等)您在
out
上使用的
out
声明的类型存储在
System.class
中,并由编译器和JVM使用。好的,最后一个也是最后一个问题。如果我在Test.java文件中运行例如System.out.println(“Test”)。首先编译器告诉我这个调用是java.lang.System.out.println(“Test”)编译之后,我们有一个Test.class文件。JVM现在加载Test.class文件,并看到java.lang.System.out.println(“Test”)然后,JVM加载、链接并初始化java.io.PrintStream类,即java.io.PrintStream.class。然后JVM可以调用println()方法,对吗?