2

我有一个简单的代码:

public class Hello
{
    public static void main(String[] args)
    {
        System.out.println("Hello World");
    }
}

我知道Object在每个java程序中默认都会导入类,但是我想问PrintStream如果我们使用print()println()函数,是否也默认导入了类?

因为Object类属于java.lang包,PrintStream类属于java.io包,所以如果默认不导入,那我们怎么能使用类的println()方法PrintStream呢?

如果它(PrintStream类)默认不导入,那反编译器为什么要导入呢?

这是反编译后的输出: 检查此图像

4

3 回答 3

1

Java 程序中的中间表达式类型不需要在源代码级别导入。只有当您将此类表达式的值分配给已声明的变量时,您才必须使其类型显式;那时您必须添加导入(或使用限定名称)。

在您的情况下,System.out是这样一个中间表达式;它的类型确实是java.io.PrintStream,默认情况下导入,因为它不在java.lang. 如果您将课程修改为

import java.io.PrintStream;
public class Hello {
    public static void main(String[] args)
    {
        PrintStream myOut = System.out;
        myOut.println("Hello World");
    }
}

您需要添加导入语句,或使用限定名称,如

public class Hello {
    public static void main(String[] args)
    {
        java.io.PrintStream myOut = System.out;
        myOut.println("Hello World");
    }
}

在字节码级别,情况有所不同:由于需要加载所有依赖项以使 JVM 能够执行代码,所有依赖项都列在.class文件中,包括中间表达式的类型。显然,OP 屏幕截图中使用的反编译器不够聪明,无法意识到在源代码级别不需要此类导入,因此它只是为.class文件中列出的所有依赖项创建导入语句。

于 2015-08-20T21:21:55.363 回答
0

我想问一下,如果我们使用 print() 或 println() 函数,是否也默认导入 PrintStream 类

不,来自 JLS

编译单元自动访问其包中声明的所有类型,并自动导入预定义包中声明的所有公共类型java.lang

所以你可以使用System,因为它属于java.lang.


那么如果默认不导入,那么我们如何使用 PrintStream 类的 println() 方法呢?

因为你的类型System.out可以访问,所以你可以使用所有可见的方法System.out

于 2015-08-20T18:36:46.213 回答
0

为什么反编译器要导入它

看起来像您正在使用的反编译器中的错误。此处完全不需要此导入。

您可以完全不使用导入进行编程,只需使用完全限定的类名,如下所示:

java.io.PrintStream out = System.out;

使用导入只是为了方便,因此您可以在代码中使用简单的类名。相同的简单名称可能会出现在不同的包中(例如,java.awt.Listand java.util.List),因此要解决这种歧义,您必须使用完整的类名或导入您想要的类名(如果您想同时使用它们,您仍然会必须使用其中之一的全名)。正如您正确提到 java.lang的,默认情况下始终只导入来自的类。同样,这样做是为了方便,所以您可以使用 justSystem而不是java.lang.System(虽然java.lang.System.out.println()也是有效的)。

在您的示例中,由于您没有直接PrintStream在源代码中提及,因此无需导入它。导入与类加载没有任何共同之处(发生在运行时,而不是在编译期间)。

于 2015-08-22T03:27:45.793 回答