Java包名必须全小写、禁用下划线,因JVM和工具链将包名映射为文件路径,跨平台大小写敏感性不一致;域名倒写是惯例而非强制,但可避免命名冲突;import失效常见于默认包引用、静态导入误用或IDE/模块配置缺失;同名类需显式全限定名;模块系统中import与requires缺一不可。

Java包名为什么必须全小写、不能用下划线
因为JVM规范和主流工具链(如javac、IDEA、Maven)默认把包名映射为文件系统路径,而路径在Windows/macOS/Linux上对大小写敏感性不一致,但统一转小写最稳妥。用大写字母或_会导致编译通过但运行时报NoClassDefFoundError或类加载失败。
- 合法:
com.example.util、org.apache.commons.lang3 - 非法:
com.Example.Util(首字母大写)、com.example.my_tool(含_)、com.example.123api(数字开头) - 域名倒写是惯例,不是强制——但不用它,团队协作时容易撞名,Maven中央仓库也拒绝非域名格式的发布包
import语句不生效的三个常见原因
import只是告诉编译器“这个类我打算用”,不导入就不会报错,但一调用就炸。真正失效往往是因为路径、作用域或静态导入误用。
- 类在默认包里,却写了
import com.example.MyClass:Java 8+已禁止跨包引用默认包中的类 - 用了静态导入
import static java.lang.Math.*,却想调用Arrays.asList()——asList不是Math的静态方法,得另写import java.util.Arrays - IDE没刷新依赖,或模块路径(module-path)下jar包未正确声明
requires,此时import语法没错,但编译器根本找不到那个类
同一个类被多个import引入时,编译器怎么选
Java不支持“重载import”,也不允许同名类共存于同一编译单元。如果两个import指向不同包下的同名类(比如java.util.Date和java.sql.Date),你必须显式写全限定名,否则编译失败。
- 错误写法:
import java.util.Date; import java.sql.Date;→ 编译报错The type Date is ambiguous - 正确做法:只import一个,另一个用全名,例如
java.sql.Date sqlDate = new java.sql.Date(0); - 别指望IDE自动帮你“猜”——它可能默认补全
java.util.Date,但业务逻辑需要的是sql.Date,结果类型错配,运行时出问题
模块系统(Java 9+)下import和requires的关系
import管的是源码里怎么写类名,requires(在module-info.java里)管的是编译/运行时能不能加载那个模块里的类。两者缺一不可,且层级不同。
立即学习“Java免费学习笔记(深入)”;
- 只写
import javafx.scene.control.Button,但module-info.java里没requires javafx.controls→ 编译失败,提示package javafx.scene.control is not visible - 写了
requires java.base(默认已有),但忘了requires transitive gson→ 其他模块引用你模块时,拿不到Gson类,会报ClassNotFoundException - 第三方库没模块化(比如老版本
commons-lang3),就得用requires static或干脆退回到classpath模式
包机制本身没变,但模块加了一层访问控制——光名字对了不够,还得“门开着”。










