Java 中的默认包问题

2019-03-02 21:29:11 +08:00
 skai0dev

起因

今天看《 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 中一个项目模块到底有几个默认包啊,根据上面实验应该是一个,但书和文档说默认包都是和目录相关联的,所以每个目录下面都有一个默认包?还是说这个主要取决于系统?

4100 次点击
所在节点    Java
3 条回复
skai0dev
2019-03-02 23:18:26 +08:00
没人吗?😂😂
Belmode
2019-03-02 23:34:57 +08:00
默认指的是 classpath 根路径下,没有包的 class 和 java 文件。你想的太多了。
skai0dev
2019-03-03 10:34:41 +08:00
@Belmode 多谢指教,我有点跑偏了 ^_^

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/540412

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX