从 TypeScript 到 Java(1):理解类与包结构
系列导读: 本系列面向有 TypeScript 基础的开发者,帮助你快速掌握 Java 的核心概念与语言特性。 第一篇,我们从最基础也是最重要的部分开始------类与包结构(Class & Package)。
Java 是一个"万物皆类"的世界,所有代码都必须定义在类中,并且类必须归属于某个包(package),而TypeScript 则更灵活,模块与文件关系松散。

💡 为什么要从类与包开始学?
在 TypeScript 中,我们习惯了灵活的模块系统: 一个文件可以导出函数、对象、类,也可以随意组合模块结构。
但在 Java 世界里,一切都更"严格"和"有序":
- 所有代码都必须定义在 类(class) 中;
- 每个文件只能包含 一个 public 类;
- 类所在的包(package)必须与 文件夹路径完全对应;
- 类名、文件名、包名,都遵循固定规则。
这种看似"繁琐"的规则,实际上是 Java 构建大规模工程可维护性的基础。
🧱 Java 中的类结构
让我们从最简单的 Java 类开始:
java
// 文件路径:src/main/java/com/example/demo/HelloWorld.java
package com.example.demo; // 包声明必须在文件首行
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, Java!");
}
}
逐行解释:
package com.example.demo;声明该类属于com.example.demo包,对应的文件夹路径为com/example/demo/。public class HelloWorld类名必须与文件名一致。public static void main(String[] args)这是 Java 应用程序的入口方法。
在 TypeScript 中,你可能写:
typescript
export function hello() {
console.log("Hello, TypeScript!");
}
两者看似相似,但 TypeScript 文件本身就是一个模块; 而 Java 中,模块(package)是通过目录 + 声明共同定义的。
🗂️ 包(Package)与目录结构
Java 通过包组织代码,类似于命名空间。 一个典型的包名使用 反转的域名:
lua
com.example.project
org.apache.commons
io.github.username.library
结构示意:
css
src/
└── main/
└── java/
└── com/
└── example/
├── model/
│ └── User.java
├── service/
│ └── UserService.java
└── App.java
每个子文件夹对应一个包。 当你在 UserService.java 中引用 User 时,需要显式导入:
java
import com.example.model.User;
对比 TypeScript:
typescript
import { User } from "./model/User";
区别在于:
- TypeScript 的模块是文件级的;
- Java 的包是目录级的;
- Java 编译器依赖包名确定类路径,因此目录结构必须严格匹配。
⚙️ 默认包与访问规则
如果一个类没有显式写 package,它会自动归入 默认包(default package):
java
public class Demo {}
但这样做 不推荐,因为:
- 默认包下的类无法被有包声明的类导入;
- 在大型项目中容易冲突;
- 几乎所有生产项目都会使用命名包。
最佳实践: 始终为你的项目定义根包名,例如:
com.yourcompany.project
这能保证项目结构清晰、命名不冲突。
📦 导入与可见性
在 TypeScript 中你使用 import/export; 在 Java 中,通过 import 指令引用其他包的类:
java
import com.example.utils.Logger;
public class App {
public static void main(String[] args) {
Logger.log("Start app");
}
}
Java 的导入有三种形式:
- 导入单个类:
import com.example.User; - 导入整个包:
import com.example.*; - 导入静态成员(Java 5+):
import static com.example.Utils.PI;
建议只导入需要的类,避免 * 导入污染命名空间。
🚀 实战建议:动手写一个多包小项目
可以尝试创建如下项目结构:
com.example.app
├── model/
│ └── Product.java
├── service/
│ └── ProductService.java
└── App.java
- 在
Product.java中定义一个简单类; - 在
ProductService.java中使用它; - 在
App.java的main方法中调用服务; - 编译运行,观察包结构如何影响导入。
通过亲手写一遍,你会立刻体会到 Java 的包系统是如何组织大规模项目的。
🧭 TypeScript 思维迁移图
| TypeScript 概念 | Java 对应概念 | 关键区别 |
|---|---|---|
| 模块(module) | 包(package) | Java 强制目录与包一致 |
| export class | public class | Java 一个文件一个 public 类 |
| import {...} from | import com.xxx | Java 编译依赖包路径 |
| 任意文件执行 | main 方法入口 | Java 程序需从 main 启动 |
✅ 小结
从 TypeScript 过渡到 Java,理解 类与包结构 是第一步。 Java 的严格结构看似限制自由,但正是这种约束,保证了项目的可维护性和可扩展性。
记住两句话:
- Java 中"一切皆类";
- 包名与目录结构必须完全对应。
当你能熟练地创建多层包结构、理解类之间的组织关系时, 你已经迈入 Java 世界的第一扇大门。
👉 下一篇预告
《从脚本执行到 main 方法:理解 Java 的程序入口》 我们将深入讲解 main 方法的执行逻辑、参数机制和运行时结构。