V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
skai0dev
V2EX  ›  Java

Java 中的默认包问题

  •  
  •   skai0dev · 2019-03-02 21:29:11 +08:00 · 4110 次点击
    这是一个创建于 2104 天前的主题,其中的信息可能已经有所发展或是发生改变。

    起因

    今天看《 Java 编程思想》第六章的时候看到这样一句话:

    一定要记住,相同目录下的所有不具有明确 package 声明的文件,都被视作是该目录下默认包的一部分。

    以前没有深入了解过默认包,以为默认包就是文件所在的目录所表示的包,然后一想这样的话那写不写 package 语句不就没什么必要了吗,都是以文件夹区分的,然后试了一下,发现我错了。所以就打算看看这个默认包到底是怎么回事。

    实验

    OS: Windows 10
    JDK: OracleJDK 1.8
    IDE: IntelliJ IDEA

    代码的目录结构是这样的:

    src
     ├─TopLevel.java
     │
     └─transformer
         ├─SecondLevel.java
         │
         ├─autobot
         │   ├─Bumblebee.java
         │   ├─LowLevel.java
         │   └─OptimusPrime.java
         │
         └─decepticon
             ├─LowLevelCopy.java
             ├─Megatron.java
             └─Starscream.java
    

    这些类都只有一个 main 方法输出类名,其中以 Level 结尾的.java文件都是没有 package 语句的。

    因为用的 IDEA,没有 package 语句的类名(除了 TopLevel 类)下面出红线了,说是 missing package statement,但是代码能够运行且没有错误,这说明可以没有 package 语句。

    在 transformer.autobot 包里的 Bumblebee (有 package 语句)的 main 方法里引用 LowLevel (没有 package 语句)的 main 方法,IDEA 自动补全并没有显示 LowLevel,手写上去后编译没过,说是找不到符号,这说明默认包里的类不能被非默认包里的类引用。(后来查资料说是可以通过反射来引用)

    在 LowLevel 的 main 方法中引用了 transformer.autobot 包里的 Bumblebee 的 main 方法,它会导入 Bumblebee,然后代码也能正确运行,这说明默认包可以引用非默认包里的类。

    在 LowLevel 的 main 方法中引用 transformer.decepticon 包里的 LowLevelCopy 的 main 方法,IDEA 自动补全会显示 LowLevelCopy,只是类名是红色(没有红线),代码也能正确运行,然后把 LowLevel 类声明的 public 去掉,也能正确运行,这说明两个类应该是在同一个包内。

    在 TopLevel 和 SecondLevel 中也能够引用 LowLevel 和 LowLevelCopy,而且在后两者中引用前两者也可以,(有个问题就是在引用 TopLevel 时类名就是正常颜色,而引用 SecondLevel 或者 LowLevel 时类名就是红色,不过这应该时 IDEA 的原因)这说明无论没有 package 语句的.java文件在项目中的哪个文件夹下,最后默认包只有一个。

    查资料

    查了一会资料查到 StackOverflow 上的一个问题: https://stackoverflow.com/questions/2335211/what-is-the-default-package-in-which-my-classes-are-put-if-i-dont-specify-it

    根据答案中的一个链接找到了 Oracle 的文档: https://docs.oracle.com/javase/specs/jls/se8/html/jls-7.html#jls-7.4.2

    然后看到这句话:

    An implementation of the Java SE platform must support at least one unnamed package. An implementation may support more than one unnamed package, but is not required to do so. Which compilation units are in each unnamed package is determined by the host system.

    又看到这句话:

    In implementations of the Java SE platform that use a hierarchical file system for storing packages, one typical strategy is to associate an unnamed package with each directory; only one unnamed package is observable at a time, namely the one that is associated with the "current working directory". The precise meaning of "current working directory" depends on the host system.

    然后我就有点迷糊了,Java 中一个项目模块到底有几个默认包啊,根据上面实验应该是一个,但书和文档说默认包都是和目录相关联的,所以每个目录下面都有一个默认包?还是说这个主要取决于系统?

    3 条回复    2019-03-03 10:34:41 +08:00
    skai0dev
        1
    skai0dev  
    OP
       2019-03-02 23:18:26 +08:00 via Android
    没人吗?😂😂
    Belmode
        2
    Belmode  
       2019-03-02 23:34:57 +08:00 via Android   ❤️ 1
    默认指的是 classpath 根路径下,没有包的 class 和 java 文件。你想的太多了。
    skai0dev
        3
    skai0dev  
    OP
       2019-03-03 10:34:41 +08:00
    @Belmode 多谢指教,我有点跑偏了 ^_^
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5861 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 01:45 · PVG 09:45 · LAX 17:45 · JFK 20:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.