【问题标题】:Default Classes imported in javajava中导入的默认类
【发布时间】:2015-11-14 12:59:53
【问题描述】:

我有一个简单的代码:

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

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

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

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

这是反编译后的输出:

【问题讨论】:

    标签: java class import printstream


    【解决方案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");
        }
    }
    

    你需要添加import语句,或者使用限定名

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

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

    【讨论】:

    • @Arend-检查反编译器的输出。
    • @RajMalhotra 添加了一段解释反编译器输出中的虚假导入
    【解决方案2】:

    为什么反编译器要导入它

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

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

    java.io.PrintStream out = System.out;
    

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

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

    【讨论】:

      【解决方案3】:

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

      不,from the JLS

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

      所以你可以使用System,因为it belongs to java.lang


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

      因为System.out对你的类型来说是accessible,所以你可以使用System.out的所有可见方法

      【讨论】:

      • @RC.-但是 println() 是 PrintStream 类的一个方法,那么我们如何在不导入的情况下使用它。
      • 进一步解释(适用于更一般的情况):当类加载器加载 java.lang.System 时,它将处理 java.lang.System 具有的任何导入,其中包括 java.lang.System 具有的导入。 io.PrintStream (以及上下线)。因此,当您调用 System.out.println() 时,所有需要的类都已加载并准备就绪(正如最近的编辑所解释的那样)。
      猜你喜欢
      • 1970-01-01
      • 2011-01-12
      • 2016-11-06
      • 2018-10-14
      • 2011-01-03
      相关资源
      最近更新 更多