Java

Eclipseで最初のJavaプロジェクトを作る(パッケージ/クラス設計の基本)

初回プロジェクトの作成から、正しいパッケージ設計・クラス分割・動作確認までをステップ形式で解説。記事のとおりに進めれば、Eclipseで「動くJavaアプリ」を作りながら、現場でも通用する設計の土台が身につきます。

本記事のゴールと前提

  • Eclipseで新規Javaプロジェクトを正しく作れる
  • 適切なパッケージ構成クラス分割で小さなアプリを組み立てられる
  • Run As > Java Application で実行して結果を確認できる

JDKやEclipseの導入がまだの方は、先に 導入記事(JDK設定まで) をご覧ください。

新規プロジェクト作成(Eclipse)

  1. File > New > Java Project を選択。
  2. Project namefirst-java-project(空白や日本語は避ける)
  3. JREUse an execution environment JRE: JavaSE-21(またはインストール済みJDK)
  4. Project layout:既定のままでOK(ソースは src
  5. Module(module-info.java)について:最初は作らないほうが簡単。もし自動作成された場合は一旦削除して構いません。
  6. Finish(初回だけ「Open Associated Perspective?」は Yes でOK)。

続けて、src を右クリック → New > Package でパッケージを作ります(次章)。

パッケージ設計の基礎(命名規則と層)

パッケージは全部小文字で、逆ドメイン形式が一般的です。個人開発や学習では com.example から始めると無難。

com.example.todo
├─ domain      (アプリの中心的なデータ構造:Taskなど)
├─ repository  (データの保存・取得:DBやメモリ)
├─ service     (業務ロジック:検証・集約・操作)
└─ app         (UI層/エントリポイント:mainメソッド)
    
  • domain:ビジネスで扱う名詞(Task, User, Order など)
  • repository:データのCRUDを隠蔽。後でDBに差し替えても他層に影響が少ない
  • service:ユースケース(「タスク追加」「完了にする」等)の手順を1か所に集約
  • app:入出力部分。今回はコンソール。将来Web/UIに変わっても他層は再利用できる

この4層に分けるだけで、コードの見通しと拡張性が大幅に上がります。

サンプルで学ぶ:コンソールToDoアプリ

最小限のToDo管理を作ります。タスクの追加/一覧/完了を、レイヤごとに役割分担して実装します。

1) domain:エンティティ(Task)

package com.example.todo.domain;

import java.time.LocalDateTime;
import java.util.Objects;

public class Task {
  private final long id;
  private String title;
  private boolean done;
  private final LocalDateTime createdAt;

  public Task(long id, String title) {
    this.id = id;
    this.title = title;
    this.done = false;
    this.createdAt = LocalDateTime.now();
  }

  public long getId() { return id; }
  public String getTitle() { return title; }
  public boolean isDone() { return done; }
  public LocalDateTime getCreatedAt() { return createdAt; }

  public void rename(String newTitle) {
    if (newTitle == null || newTitle.isBlank()) {
      throw new IllegalArgumentException("タイトルは1文字以上で入力してください。");
    }
    this.title = newTitle;
  }

  public void markDone() { this.done = true; }

  @Override
  public String toString() {
    return (done ? "[x] " : "[ ] ") + id + ": " + title + " (" + createdAt + ")";
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Task)) return false;
    Task task = (Task) o;
    return id == task.id;
  }

  @Override
  public int hashCode() {
    return Objects.hash(id);
  }
}

2) repository:データ取得

package com.example.todo.repository;

import com.example.todo.domain.Task;
import java.util.List;
import java.util.Optional;

public interface TaskRepository {
  Task save(Task task);
  Optional<Task> findById(long id);
  List<Task> findAll();
}
package com.example.todo.repository;

import com.example.todo.domain.Task;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class InMemoryTaskRepository implements TaskRepository {
  private final Map<Long, Task> store = new ConcurrentHashMap<>();

  @Override
  public Task save(Task task) {
    store.put(task.getId(), task);
    return task;
  }

  @Override
  public Optional<Task> findById(long id) {
    return Optional.ofNullable(store.get(id));
  }

  @Override
  public List<Task> findAll() {
    List<Task> list = new ArrayList<>(store.values());
    list.sort(Comparator.comparing(Task::getCreatedAt));
    return list;
  }
}

3) service:業務ロジック

package com.example.todo.service;

import com.example.todo.domain.Task;
import com.example.todo.repository.TaskRepository;

import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

public class TaskService {
  private final TaskRepository repository;
  private final AtomicLong sequence = new AtomicLong(1L);

  public TaskService(TaskRepository repository) {
    this.repository = repository;
  }

  public Task add(String title) {
    if (title == null || title.isBlank()) {
      throw new IllegalArgumentException("タイトルを入力してください。");
    }
    long id = sequence.getAndIncrement();
    Task task = new Task(id, title.trim());
    return repository.save(task);
  }

  public List<Task> list() {
    return repository.findAll();
  }

  public Task complete(long id) {
    Task task = repository.findById(id)
        .orElseThrow(() -> new IllegalArgumentException("指定IDのタスクが見つかりません: " + id));
    task.markDone();
    repository.save(task);
    return task;
  }

  public Task rename(long id, String newTitle) {
    Task task = repository.findById(id)
        .orElseThrow(() -> new IllegalArgumentException("指定IDのタスクが見つかりません: " + id));
    task.rename(newTitle);
    repository.save(task);
    return task;
  }
}

4) app:エントリポイント(Main)

package com.example.todo.app;

import com.example.todo.repository.InMemoryTaskRepository;
import com.example.todo.repository.TaskRepository;
import com.example.todo.service.TaskService;

import java.util.Scanner;

public class Main {
  private static void printHelp() {
    System.out.println("=== ToDo Commands ===");
    System.out.println(" add <title>     : タスク追加");
    System.out.println(" list             : 一覧表示");
    System.out.println(" done <id>        : 完了にする");
    System.out.println(" rename <id> <t>  : タイトル変更");
    System.out.println(" help             : コマンド一覧");
    System.out.println(" exit             : 終了");
    System.out.println("=====================");
  }

  public static void main(String[] args) {
    TaskRepository repo = new InMemoryTaskRepository();
    TaskService service = new TaskService(repo);

    try (Scanner sc = new Scanner(System.in)) {
      printHelp();
      while (true) {
        System.out.print("> ");
        String cmd = sc.next();
        switch (cmd) {
          case "add":
            String title = sc.nextLine().trim();
            System.out.println("追加: " + service.add(title));
            break;
          case "list":
            service.list().forEach(System.out::println);
            break;
          case "done":
            long id = sc.nextLong();
            System.out.println("完了: " + service.complete(id));
            break;
          case "rename":
            long rid = sc.nextLong();
            String nt = sc.nextLine().trim();
            System.out.println("変更: " + service.rename(rid, nt));
            break;
          case "help":
            printHelp();
            break;
          case "exit":
            System.out.println("Bye.");
            return;
          default:
            System.out.println("不明なコマンド。help を参照してください。");
        }
      }
    }
  }
}

5) 実行と確認

  1. Package ExplorerMain を右クリック → Run As > Java Application
  2. コンソールに > が出たら成功。以下の例を試す:
add 牛乳を買う
add 本を10ページ読む
list
done 1
rename 2 本を15ページ読む
list
exit

メモリ内リポジトリなので、Eclipseを終了するとデータは消えます。後日、ファイル保存やDBに差し替えてみましょう(repository層だけ差し替えればOK)。

設計の基本原則(最初に押さえる3点)

  1. 関心の分離(SoC):入出力(app)と業務ロジック(service)とデータアクセス(repository)を分ける。
  2. 不変条件の保持:domainのコンストラクタ/メソッドで不正な状態を拒否(例:タイトルの空文字禁止)。
  3. 依存方向は内側へ:app → service → repository → domain の一方向。下位層は上位層を参照しない。

この3つを守るだけで、クラスが巨大化しにくく、機能追加や差し替えが楽になります。

よくあるエラーと対処

  • Could not find or load main classMain のパッケージ宣言(package com.example.todo.app;)とフォルダ構成が一致しているか確認。
  • 違うJREで実行されるProject > Properties > Java Build Path → JRE System Library をJDK21に。Project FacetsCompiler のバージョンも見直し。
  • module-info.javaが邪魔:最初は削除してOK。モジュールは慣れてから。
  • 文字化けPreferences > General > Workspace > Text file encoding を UTF-8 に。コンソールも UTF-8 (必要なら VM引数に -Dfile.encoding=UTF-8)。
  • ビルドされないProject > Build Automatically を有効化。ダメなら Project > Clean…

Eclipse便利設定(最初に済ませると幸せ)

  • Save Actions:保存時に自動整形・不要import削除(Preferences > Java > Editor > Save Actions)。
  • FormatterPreferences > Java > Code Style > Formatter でプロファイル作成(チーム運用の第一歩)。
  • Organize Imports:ショートカット割当(例:Windows: Ctrl+Shift+O, Mac: ⌘⇧O)。
  • Quick FixCtrl+1 / ⌘1 で警告から即修正。

この次に知りたい情報

導入〜完成チェックリスト

  • Java Project を first-java-project で作成した
  • com.example.todo 配下に domain/repository/service/app を作成した
  • 各クラスを入力し、エラーがない(電球マークはQuick Fixで解消)
  • MainRun As で実行してコマンドが動作した
  • Save Actions / Formatter を設定してコードが自動整形される

FAQ

パッケージ名は日本語でもいい?

推奨しません。英小文字+ドット区切り(例:com.example.todo)に統一しましょう。

クラスは1ファイル1クラス?

基本は1ファイル1公開クラス(public)です。小規模の補助クラスはパッケージプライベートで同パッケージに置いてOK。

テストはどう書く?

次段のMaven/Gradle導入後に JUnit を使うのが定番です。まずは service のメソッド単位から始めましょう。

著者:まーくん|更新日:2025-08-25

【保存版】Eclipseのインストール手順(JDK設定まで)Mac/Windows対応

EclipseのインストールからJDK設定、JAVA_HOME / PATHの正しい通し方まで。Mac/Windowsごとに手順を分け、つまずきポイントとチェックリストも付けました。

この記事のゴールと前提

  
  • Mac/WindowsでJDKを正しく導入し、JAVA_HOME/Pathを設定できる
  • Eclipse(Pleiades All in One)を迷わず入れられる
  • 導入直後にHello, World!を実行できる

配布元:JDKはOracle公式、Eclipseは日本語化済みのPleiades(willbrains.jp)。WindowsのJDKは Oracle Downloads から。

Mac編(JDK → 環境変数 → Eclipse)

1. JDKのインストール

  1. OracleのJDKダウンロードにアクセスし、macOSを選択。
  2. CPUに合わせてx64またはaarch64(Apple Silicon: M1/M2/M3)を選び、.dmgをダウンロード。
  3. ダウンロードした.dmgを開き、ウィザードに従ってインストール。
補足:迷ったらLTS版(例:JDK 21)を選んでおくと安定します。

2. 環境変数の設定(JAVA_HOME/PATH)

Macは標準の/usr/libexec/java_homeを使うと安全です(複数JDKの切替に強い)。

# zsh(標準)を想定
echo 'export JAVA_HOME=$(/usr/libexec/java_home -v 21)' >> ~/.zshrc
echo 'export PATH="$JAVA_HOME/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

# 確認
/usr/libexec/java_home -V
echo $JAVA_HOME
java -version
javac -version

3. Eclipse(Pleiades)導入

  1. Pleiades公式にアクセスし、Mac版をダウンロード。
  2. ダウンロードしたファイルをダブルクリックして展開し、アプリをApplicationsへドラッグ&ドロップ
  3. 初回は警告が出る場合あり。右クリック → 開くで回避。

4. 動作確認(Eclipse側)

  1. Eclipse起動 → Preferences > Java > Installed JREsでJDKを追加し、デフォルトにチェック。
  2. Java > Compilerでコンプライアンスを21に。
  3. File > New > Java Project → クラスを作成し、次のコードを実行。
public class Hello {
  public static void main(String[] args) {
    System.out.println("Hello, World!");
  }
}

Windows編(JDK → 環境変数 → Eclipse)

1. JDKのインストール

  1. Oracle Downloadsへ。
  2. Windows x64用のインストーラ(.msi / .exe)をダウンロード。
  3. 管理者権限で実行し、指示に従ってインストール。

2. 環境変数の設定(JAVA_HOME/PATH)

GUIでの設定(推奨)

  1. スタートメニューで「環境変数」と検索 → システム環境変数の編集環境変数(N)…
  2. システム環境変数新規(N)…
    変数名:JAVA_HOME
    変数値:C:\Program Files\Java\jdk-21(例。binは付けない
  3. Pathを選択 → 編集新規%JAVA_HOME%\binを追加。
  4. OKで閉じて新しいコマンドプロンプトを開く。

コマンドで一括設定(管理者)

:: JDKの場所に合わせて変更してください
setx /M JAVA_HOME "C:\Program Files\Java\jdk-21"
setx /M PATH "%PATH%;%JAVA_HOME%\bin"

確認コマンド

echo %JAVA_HOME%
java -version
javac -version

3. Eclipse(Pleiades)導入

  1. Pleiades公式Windows版をダウンロード。
  2. zipを解凍し、C:\pleiades\など日本語や空白のないパスへ配置。
  3. eclipse.exeを起動。ワークスペースはC:\workspace等の半角英数字に。

4. 動作確認(Eclipse側)

  1. Window > Preferences > Java > Installed JREsでJDKを追加し、デフォルトに。
  2. Java > Compilerでコンプライアンスを21に。
  3. Hello, World! を作成して実行(Mac編と同じ)。

よくあるトラブルと対処

  • java が見つからない:WindowsはPathに%JAVA_HOME%\binが入っているか、Macは$JAVA_HOME/binがPATHの先頭か確認。ターミナルを新しく開く。
  • Eclipseが古いJREで動くInstalled JREsのチェック先とJava Compilerを見直し。プロジェクトの「JRE System Library」も確認。
  • Apple Siliconで遅い/起動しない:aarch64版のJDK/Eclipseを使用。Rosetta経由を避ける。

この次に知りたい情報

FAQ

JAVA_HOMEはどこを指せばいい?

JDKのルートフォルダを指定します(Windows例:C:\Program Files\Java\jdk-21、Macは/usr/libexec/java_homeの出力)。binは付けません。

JDKとJREの違いは?

JREは実行環境、JDKはコンパイル含む開発環境。開発にはJDKが必要です。

Oracle以外のJDKでもよい?

はい(例:Temurin)。ただし本記事はOracle JDKを前提に記述しています。

著者:まーくん|更新日:2025-08-24