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.streamStream 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 的可見性