从 TypeScript 到 Java(1):理解类与包结构

从 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!");
    }
}

逐行解释:

  1. package com.example.demo; 声明该类属于 com.example.demo 包,对应的文件夹路径为 com/example/demo/
  2. public class HelloWorld 类名必须与文件名一致。
  3. 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 的导入有三种形式:

  1. 导入单个类:import com.example.User;
  2. 导入整个包:import com.example.*;
  3. 导入静态成员(Java 5+):import static com.example.Utils.PI;

建议只导入需要的类,避免 * 导入污染命名空间。

🚀 实战建议:动手写一个多包小项目

可以尝试创建如下项目结构:

复制代码
com.example.app
 ├── model/
 │    └── Product.java
 ├── service/
 │    └── ProductService.java
 └── App.java
  • Product.java 中定义一个简单类;
  • ProductService.java 中使用它;
  • App.javamain 方法中调用服务;
  • 编译运行,观察包结构如何影响导入。

通过亲手写一遍,你会立刻体会到 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 方法的执行逻辑、参数机制和运行时结构。

相关推荐
holidaypenguin几秒前
antd 5 + react 18 + vite 7 升级
前端·react.js
梁同学与Android几秒前
Android ---【经验篇】阿里云 CentOS 服务器环境搭建 + SpringBoot项目部署(二)
android·spring boot·后端
小满zs2 分钟前
Next.js第十五章(Image)
前端·next.js
tangbin5830853 分钟前
iOS Swift 可选值(Optional)详解
前端·ios
孟祥_成都5 分钟前
nest.js / hono.js 一起学!日志功能/统一返回格式/错误处理
前端·node.js
用户2190326527359 分钟前
SpringBoot自动配置:为什么你的应用能“开箱即用
java·spring boot·后端
_膨胀的大雄_9 分钟前
01-创建型模式
前端·设计模式
小林rush12 分钟前
uni-app跨分包自定义组件引用解决方案
前端·javascript·vue.js
我的一行13 分钟前
已有项目,接入pnpm + turbo
前端·vue.js