Java Package 與 Import
Package(套件)是 Java 用來組織和管理類別的機制,類似於檔案系統中的資料夾。
什麼是 Package
Package 可以:
- 組織類別:將相關的類別放在一起
- 避免命名衝突:不同 package 可以有相同名稱的類別
- 控制存取:使用存取修飾子控制可見性
宣告 Package
在 Java 檔案的第一行宣告:
package com.example.myapp;
public class MyClass {
// ...
}
命名慣例
- 全部使用小寫字母
- 使用反向網域名稱作為前綴
- 用點
.分隔階層
package com.google.gson;
package org.apache.commons.lang3;
package tw.com.mycompany.project;
目錄結構
Package 對應實際的目錄結構:
src/
└── com/
└── example/
└── myapp/
├── Main.java
├── model/
│ └── User.java
└── util/
└── Helper.java
// src/com/example/myapp/Main.java
package com.example.myapp;
// src/com/example/myapp/model/User.java
package com.example.myapp.model;
// src/com/example/myapp/util/Helper.java
package com.example.myapp.util;
Import 匯入
使用其他 package 的類別時,需要使用 import:
package com.example.myapp;
import java.util.ArrayList;
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
HashMap<String, Integer> map = new HashMap<>();
}
}
匯入單一類別
import java.util.ArrayList;
import java.time.LocalDate;
匯入整個 Package
使用 * 匯入 package 下的所有類別:
import java.util.*; // 匯入 java.util 下所有類別
注意:
*不會匯入子 package
import java.util.*; // 只匯入 java.util
import java.util.stream.*; // 需要另外匯入子 package
匯入靜態成員
使用 import static 匯入靜態方法或常數:
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
import static java.lang.System.out;
public class Main {
public static void main(String[] args) {
out.println(PI); // 不需要 Math.PI
out.println(sqrt(16)); // 不需要 Math.sqrt()
}
}
匯入所有靜態成員:
import static java.lang.Math.*;
public class Main {
public static void main(String[] args) {
double result = sin(PI / 2) + cos(0) + pow(2, 3);
}
}
不需要 Import 的情況
1. java.lang 套件
java.lang 自動匯入,不需要明確 import:
// 這些類別不需要 import
String s = "Hello";
Integer n = 10;
System.out.println("Hi");
Math.abs(-5);
2. 同一個 Package
同一個 package 內的類別可以直接使用:
// User.java
package com.example.model;
public class User {
private String name;
}
// Order.java
package com.example.model;
public class Order {
private User user; // 同 package,不需要 import
}
3. 完整類別名稱
使用完整的類別名稱(Fully Qualified Name)時不需要 import:
public class Main {
public static void main(String[] args) {
java.util.ArrayList<String> list = new java.util.ArrayList<>();
java.time.LocalDate today = java.time.LocalDate.now();
}
}
這在處理命名衝突時很有用:
import java.util.Date;
public class Main {
public static void main(String[] args) {
Date utilDate = new Date(); // java.util.Date
java.sql.Date sqlDate = new java.sql.Date(0); // 使用完整名稱
}
}
常用的 Java 標準套件
| Package | 說明 |
|---|---|
java.lang | 核心類別(自動匯入) |
java.util | 集合、日期、工具類別 |
java.io | 輸入輸出 |
java.nio | 新的 I/O |
java.time | 日期時間 API |
java.net | 網路 |
java.sql | 資料庫 |
java.math | 數學運算 |
java.text | 格式化 |
java.util.stream | Stream API |
java.util.function | 函數式介面 |
java.util.concurrent | 並發工具 |
Package 存取權限
存取修飾子與 package 的關係:
| 修飾子 | 同類別 | 同 Package | 子類別 | 其他 |
|---|---|---|---|---|
public | ✓ | ✓ | ✓ | ✓ |
protected | ✓ | ✓ | ✓ | ✗ |
| (default) | ✓ | ✓ | ✗ | ✗ |
private | ✓ | ✗ | ✗ | ✗ |
package com.example.a;
public class ClassA {
public int publicField = 1;
protected int protectedField = 2;
int defaultField = 3; // package-private
private int privateField = 4;
}
package com.example.b;
import com.example.a.ClassA;
public class ClassB {
public void test() {
ClassA a = new ClassA();
a.publicField; // ✓ 可存取
// a.protectedField; // ✗ 不同 package,非子類別
// a.defaultField; // ✗ 不同 package
// a.privateField; // ✗ private
}
}
建立自己的 Package
專案結構
myproject/
├── src/
│ └── com/
│ └── myapp/
│ ├── Main.java
│ ├── model/
│ │ ├── User.java
│ │ └── Product.java
│ ├── service/
│ │ └── UserService.java
│ └── util/
│ └── StringUtil.java
└── lib/
程式碼範例
// Main.java
package com.myapp;
import com.myapp.model.User;
import com.myapp.service.UserService;
public class Main {
public static void main(String[] args) {
UserService service = new UserService();
User user = service.findById(1);
}
}
// model/User.java
package com.myapp.model;
public class User {
private int id;
private String name;
// getters, setters...
}
// service/UserService.java
package com.myapp.service;
import com.myapp.model.User;
public class UserService {
public User findById(int id) {
// ...
}
}
編譯與執行
# 編譯
javac -d out src/com/myapp/*.java src/com/myapp/model/*.java
# 執行
java -cp out com.myapp.Main
Import 最佳實踐
建議做法
// ✓ 明確匯入需要的類別
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
避免的做法
// ✗ 避免使用萬用字元匯入(除非真的需要很多類別)
import java.util.*;
// ✗ 避免過度使用靜態匯入
import static java.lang.Math.*;
import static java.lang.System.*;
IDE 自動管理
現代 IDE(如 IntelliJ IDEA、Eclipse)會自動:
- 加入需要的 import
- 移除未使用的 import
- 優化 import 順序
重點整理
- Package 用於組織類別,避免命名衝突
- 命名慣例:反向網域名稱 + 小寫
import匯入其他 package 的類別import static匯入靜態成員java.lang自動匯入,不需要明確 import- 同 package 的類別可直接使用
- 存取修飾子控制跨 package 的可見性