Skip to main content

複数クラスの連携

この章では、複数のクラスを組み合わせてプログラムを作成する方法を学ぶ。 クラスを適切に分割することで、コードの見通しが良くなり、チームでの開発もしやすくなる。


この章で得られるスキル:

  • ✅ 機能ごとにクラスを分けて整理できる
  • ✅ 他のクラスを呼び出して連携させられる
  • ✅ 大規模なプログラムでも見通しよく開発できる
  • ✅ チーム開発で役立つコード構成ができる

なぜこの技術が必要か

クラスを分割しないとどうなるか?

クラスを分割しないと、1つのファイルが長くなりすぎ、コードの見通しが悪くなる。
チームで開発しにくくなる。

実行してみよう(改善前):

// 1つのクラスに全てのメソッドを書くと... public class Main { public static void main(String[] args) { int sum = add(10, 20); int diff = subtract(20, 10); int product = multiply(5, 3); System.out.println("10 + 20 = " + sum); System.out.println("20 - 10 = " + diff); System.out.println("5 × 3 = " + product); // ... mainメソッドの下に何十個ものメソッドが続く } public static int add(int a, int b) { return a + b; } public static int subtract(int a, int b) { return a - b; } public static int multiply(int a, int b) { return a * b; } // ... さらに続く(実際のプロジェクトでは1000行以上になることも) }

このように、1つのファイルに全てを書くと、ファイルが長くなり、管理が大変になる。

実行してみよう(改善後):

以下は、計算用のメソッドをMathUtilsクラスに分けた例である。
実際には別ファイルになるが、ここでは実行のために1つのコードブロックにまとめている。

// MathUtils.java(計算用のメソッドをまとめた別ファイル) class MathUtils { public static int add(int a, int b) { return a + b; } public static int subtract(int a, int b) { return a - b; } public static int multiply(int a, int b) { return a * b; } } // Main.java(エントリーポイント) public class Main { public static void main(String[] args) { // MathUtilsクラスのメソッドを呼ぶ // クラス名.メソッド名()で呼び出す int sum = MathUtils.add(10, 20); int diff = MathUtils.subtract(20, 10); int product = MathUtils.multiply(5, 3); System.out.println("10 + 20 = " + sum); System.out.println("20 - 10 = " + diff); System.out.println("5 × 3 = " + product); } }

メソッドを別ファイルに分けることで、関連する機能をグループ化し、保守しやすいプログラムを作れる。

前章との繋がり

前章で学んだメソッド(関数)は、定義場所を別ファイルに切り出すことができる。 この章では、 メソッドの定義を別のクラスファイルに分けて、整理する方法 を学ぶ。


1. パッケージとは

パッケージの役割

パッケージ は、クラスを整理するための仕組み である。 複数のクラスを論理的にグループ化することで、大規模なプログラムでもクラスを管理しやすくなる。

パッケージの構造

パッケージは、ディレクトリ(フォルダ)の階層構造に対応する。

src/
com/
example/
myapp/
Main.java
Calculator.java

この場合、Main.javaCalculator.javaは、 com.example.myappパッケージに属する。

パッケージの宣言

Javaファイルの先頭に、パッケージ名を宣言する。

package com.example.myapp;

public class Main {
// ...
}

パッケージ名の命名規則

パッケージ名は、通常 すべて小文字 で、ドット(.)で区切る。

  • 例:com.example.myapp
  • 例:jp.co.company.project
【共通】

パッケージ(またはモジュール、名前空間)の概念は、多くのプログラミング言語で共通である。


2. import文

import文とは

import文 は、他のパッケージのクラスを使うための宣言 である。

基本的な書き方

import パッケージ名.クラス名;

import java.util.ArrayList;

public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
}
}

ワイルドカードimport

パッケージ内のすべてのクラスをimportする場合、*(ワイルドカード)を使う。

import java.util.*;
注意

ワイルドカードimportは便利だが、どのクラスを使っているか分かりにくくなるため、 特定のクラスだけをimportする方が推奨される。


3. Eclipseの補完機能

Eclipseの補完機能とは

Eclipseの補完機能 は、コードを効率的に書くための強力なツールである。 タイプミスを減らし、コーディング速度を大幅に向上させることができる。

自動import(Ctrl + Shift + O)

クラス名を書いた後、Ctrl + Shift + O(MacはCmd + Shift + O)を押すと、 必要なimport文が自動的に追加される

手順:

  1. クラス名を書く(例:ArrayList
  2. Ctrl + Shift + Oを押す
  3. 必要なimport文が追加される

コード補完(Ctrl + Space)

コードの途中でCtrl + Spaceを押すと、候補が表示される

使える場面:

  • クラス名の補完Arrayと入力してCtrl + SpaceArrayListが候補に出る
  • メソッド名の補完list.aと入力してCtrl + Spaceaddが候補に出る
  • 変数名の補完:宣言済みの変数名が候補に出る

テンプレート補完

特定のキーワードを入力してCtrl + Spaceを押すと、コードテンプレートが展開される。

便利なテンプレート:

  • for文forと入力してCtrl + Space→ for文のテンプレートが展開
  • if文ifと入力してCtrl + Space→ if文のテンプレートが展開
  • sysoutsysoutと入力してCtrl + SpaceSystem.out.println()に展開

定義へジャンプ(Ctrl + クリック)

Ctrl + クリック(MacはCmd + クリック)で、メソッドやクラスの定義へジャンプできる。

使い方:

  1. メソッド名やクラス名の上でCtrlキーを押しながらクリック
  2. そのメソッドやクラスが定義されているファイルへ自動的に移動する
  3. 定義を確認したら、Alt + ←(戻るボタン)で元の場所に戻れる

例:

int result = MathUtils.add(10, 20);  // addにカーソルを合わせてCtrl+クリック

MathUtils.javaaddメソッドの定義にジャンプする

ポイント

Eclipseの補完機能を積極的に活用することで、コーディングが格段に効率的になる。
最初は意識して使うようにし、慣れてくると自然に使えるようになる。


4. 複数クラスの連携

Mainクラスと処理クラス

プログラムを整理するため、以下のように役割を分担することが多い:

  • Mainクラス:プログラムの起点(mainメソッド)
  • 処理クラス:関連するメソッド(関数)をまとめたクラス

別クラスのstaticメソッドを呼び出す

前章で学んだように、メソッドは public static を付けて定義できる。 別クラスのstaticメソッドを呼び出すには、 クラス名.メソッド名() の形で呼び出す。

// MathUtils.java(別ファイル)
public class MathUtils {
public static int add(int a, int b) {
return a + b;
}
}

// Main.java
public class Main {
public static void main(String[] args) {
int result = MathUtils.add(10, 20); // クラス名.メソッド名()で呼び出す
System.out.println(result);
}
}

このように、 別ファイルで定義したメソッドを、クラス名を指定して呼び出すことができる。

ポイント

第7章で学んだメソッドを、別のクラスファイルに切り出して整理することで、コードが見やすくなる。 前章のメソッドは「同じファイル内の関数」、今回は「別ファイルの関数」という違いだけである。

よくあるエラー:クラス名のスペルミス

別クラスのメソッドを呼び出す時、クラス名のスペルを間違えるとエラーになる。

int result = MathUtil.add(10, 20);  // エラー!MathUtils ではなく MathUtil

エラーメッセージ例:

error: cannot find symbol
symbol: variable MathUtil

原因: クラス名のスペルが間違っている、またはクラスが存在しない。

解決策:

  • クラス名のスペルを確認する(大文字・小文字も区別される)
  • Eclipseの補完機能(Ctrl + Space)を使うと、正しいクラス名が候補に出る
  • Ctrl + Shift + Oで自動的にimport文を追加できる

実行してみよう:

実際の開発では、以下のように 別々のファイル として作成する:

ファイル1: MathUtils.java(計算用のユーティリティクラス)

public class MathUtils {
public static int add(int a, int b) {
return a + b;
}

public static int subtract(int a, int b) {
return a - b;
}

public static int multiply(int a, int b) {
return a * b;
}

public static int divide(int a, int b) {
return a / b;
}
}

ファイル2: Main.java(プログラムのエントリーポイント)

public class Main {
public static void main(String[] args) {
// MathUtilsクラスのstaticメソッドを呼び出す
// クラス名.メソッド名()の形で呼び出す
int sum = MathUtils.add(10, 20);
int diff = MathUtils.subtract(20, 10);
int product = MathUtils.multiply(5, 3);
int quotient = MathUtils.divide(20, 4);

System.out.println("10 + 20 = " + sum);
System.out.println("20 - 10 = " + diff);
System.out.println("5 × 3 = " + product);
System.out.println("20 ÷ 4 = " + quotient);
}
}

以下は実行可能なコード(1つのコードブロックにまとめたもの):

// MathUtils.java(別ファイル) class MathUtils { public static int add(int a, int b) { return a + b; } public static int subtract(int a, int b) { return a - b; } public static int multiply(int a, int b) { return a * b; } public static int divide(int a, int b) { return a / b; } } // Main.java(別ファイル) public class Main { public static void main(String[] args) { int sum = MathUtils.add(10, 20); int diff = MathUtils.subtract(20, 10); int product = MathUtils.multiply(5, 3); int quotient = MathUtils.divide(20, 4); System.out.println("10 + 20 = " + sum); System.out.println("20 - 10 = " + diff); System.out.println("5 × 3 = " + product); System.out.println("20 ÷ 4 = " + quotient); } }

やってみよう:

  • MathUtilsクラスに新しいstaticメソッド(例:powerで累乗計算)を追加してみよう
  • Mainクラスから新しいメソッドをMathUtils.power(2, 3)のように呼び出してみよう

5. クラスの分割の設計

役割ごとにクラスを分ける

プログラムを設計するとき、役割ごとにクラスを分ける ことが重要である。

例:成績管理システム

  • Studentクラス:生徒の情報を管理
  • Gradeクラス:成績の計算を担当
  • Mainクラス:プログラムの起点

見通しの良いコード

クラスを適切に分割することで、以下のメリットがある:

  1. 役割が明確:各クラスが何をするのかが分かりやすい
  2. 変更が簡単:1つのクラスを変更しても、他のクラスに影響しにくい
  3. チーム開発しやすい:クラスごとに担当を分けられる

クラス分割の例

実際の開発では、以下のように 役割ごとに別々のファイル として作成する:

ファイル1: Student.java(生徒の情報を管理)

public class Student {
String name;
int age;

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public void introduce() {
System.out.println("名前: " + name + ", 年齢: " + age);
}
}

ファイル2: Grade.java(成績の計算を担当)

public class Grade {
public static double calculateAverage(int[] scores) {
int sum = 0;
for (int score : scores) {
sum += score;
}
return (double) sum / scores.length;
}

public static String getGradeLevel(double average) {
if (average >= 90) {
return "優";
} else if (average >= 70) {
return "良";
} else if (average >= 60) {
return "可";
} else {
return "不可";
}
}
}

ファイル3: Main.java(プログラムのエントリーポイント)

public class Main {
public static void main(String[] args) {
// Studentクラスを使う(newの使い方は次章で学ぶ)
Student student = new Student("太郎", 18);
student.introduce();

// Gradeクラスのstaticメソッドを使う
int[] scores = {80, 90, 75};
double average = Grade.calculateAverage(scores); // クラス名.メソッド名()
String level = Grade.getGradeLevel(average);

System.out.println("平均点: " + average);
System.out.println("成績: " + level);
}
}

以下は実行可能なコード(1つのコードブロックにまとめたもの):

// Student.java(別ファイル) class Student { String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } public void introduce() { System.out.println("名前: " + name + ", 年齢: " + age); } } // Grade.java(別ファイル) class Grade { public static double calculateAverage(int[] scores) { int sum = 0; for (int score : scores) { sum += score; } return (double) sum / scores.length; } public static String getGradeLevel(double average) { if (average >= 90) { return "優"; } else if (average >= 70) { return "良"; } else if (average >= 60) { return "可"; } else { return "不可"; } } } // Main.java(別ファイル) public class Main { public static void main(String[] args) { Student student = new Student("太郎", 18); student.introduce(); int[] scores = {80, 90, 75}; double average = Grade.calculateAverage(scores); String level = Grade.getGradeLevel(average); System.out.println("平均点: " + average); System.out.println("成績: " + level); } }

やってみよう:

  • Gradeクラスに新しいstaticメソッド(例:getMaxScoreで最高点を返す)を追加してみよう
  • MainクラスからGrade.getMaxScore(scores)のように呼び出してみよう
ポイント

クラス分割は、最初から完璧にする必要はない。 プログラムが大きくなってきたら、「この部分は独立したクラスにした方が良いかも」と考えて、 少しずつリファクタリング(コードの整理)していくと良い。


まとめ

この章では、複数クラスの連携 について学んだ。

学んだ内容

  • パッケージ はクラスを整理する仕組みである
  • import文 で他のパッケージのクラスを使える
  • Eclipseの補完機能Ctrl + Shift + OCtrl + Space)を活用すると効率的にコードを書ける
  • 別クラスのstaticメソッドクラス名.メソッド名()の形で呼び出せる
  • 前章で学んだメソッド(関数)を 別ファイルに切り出して整理 できる
  • 用途ごとにファイル(クラス)、フォルダ(パッケージ)を分ける ことで、管理しやすいプログラムになる
  • 役割ごとにクラスを分ける ことで、見通しの良いコードになる

次のステップ

次の章では、例外処理 について学ぶ。 プログラム実行中に発生するエラーを適切に処理する方法を学ぶ。

その後の章で オブジェクト指向の基礎 を学び、 クラスとインスタンスの概念を深く理解していく。


演習

Javaのパッケージの役割として最も適切なものを選べ。

正解

D. 関連するクラスをグループ化してフォルダのように整理する仕組み

解説

パッケージは、関連するクラスを フォルダのようにグループ化 して整理する仕組みである。パッケージを使うことで、クラス名の衝突を避け、大規模なプロジェクトでもコードを見つけやすくなる。Javaのファイル先頭に package com.example; のように宣言する。

以下のコードの空欄を埋めて、Scannerクラスを使えるようにせよ。

// Scannerクラスをインポート
; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); } }

解答例
import java.util.Scanner;
解説

他のパッケージのクラスを使うには、import パッケージ名.クラス名; と書く。Scanner クラスは java.util パッケージに含まれているため、import java.util.Scanner; と宣言する。import文はクラス定義の前に記述する。

複数のクラスに処理を分けることのメリットとして正しいものを すべて 選べ。

1つのクラスにすべての処理を書くと、コードが長くなりすぎて管理が難しくなる。役割ごとにクラスを分けることの利点を考えてみよう。

正解

A. コードの見通しが良くなり、保守しやすくなる

C. 役割分担が明確になり、チーム開発がしやすくなる

D. 再利用しやすい部品を作れる

解説

複数クラスに分けるメリットは、コードの見通しが良くなる(A)、チーム開発がしやすくなる(C)、再利用性が高まる(D)である。実行速度の向上(B)はクラス分割のメリットではない。クラス分割は主に コードの管理しやすさ を目的としている。

Calculatorクラスにstaticな add メソッドが定義されている。以下のコードの空欄を埋めて、このメソッドを呼び出すプログラムを完成させよ。

// Calculatorクラス(別ファイル): // public static int add(int a, int b) { return a + b; } public class Main { public static void main(String[] args) { int result =
; System.out.println(result); } }

staticメソッドを呼び出すには クラス名.メソッド名() と書く。

解答例
Calculator.add(3, 5)
解説

別のクラスのstaticメソッドを呼び出すには、クラス名.メソッド名(引数) と書く。Calculator.add(3, 5) で、Calculatorクラスのaddメソッドを呼び出して結果を受け取れる。

Eclipseでコード補完(コンテンツアシスト)を呼び出すショートカットキーを選べ。

正解

D. Ctrl + Space

解説

Eclipseのコード補完(コンテンツアシスト)は Ctrl + Space で呼び出す。クラス名やメソッド名の一部を入力した状態でこのショートカットを押すと、候補が表示される。Ctrl + S は保存、Ctrl + Z は元に戻す、Ctrl + C はコピーである。

以下のプログラムを完成させよ。

要件

  • MathUtil クラスに以下のstaticメソッドを作成する
    • max(int a, int b): 2つの値のうち大きい方を返す
    • min(int a, int b): 2つの値のうち小さい方を返す
    • average(int a, int b): 2つの値の平均を返す(小数も含む)
class MathUtil { // ここにstaticメソッドを書いてください } public class Main { public static void main(String[] args) { System.out.println("最大値: " + MathUtil.max(10, 20)); System.out.println("最小値: " + MathUtil.min(10, 20)); System.out.println("平均: " + MathUtil.average(10, 20)); } }

MathUtilクラスにstaticメソッドを定義し、Mainクラスから呼び出す形にしよう。各メソッドは引数を受け取り、計算結果を返す。

解説

解答例

// MathUtilクラス
public class MathUtil {
    public static int max(int a, int b) {
        return (a > b) ? a : b;
    }

    public static int min(int a, int b) {
        return (a < b) ? a : b;
    }

    public static double average(int a, int b) {
        return (a + b) / 2.0;
    }
}

ユーティリティクラスは、関連する処理をまとめて提供するクラスである。メソッドをstaticにすることで、インスタンスを作らずに MathUtil.max(10, 20) のように直接呼び出せる。