
Java超|クラスをファイルに分ける
クラスごとに巻物を分ければ、Javaの戦士チームはもっと読みやすく、育てやすくなる。
Javaの学習を始めたばかりのころは、1つのファイルの中に複数のクラスを書いて、プログラムの動きを確認することがあります。
小さなプログラムであれば、この形でも学習しやすいです。
1つのファイルを開けば、クラスの定義も main メソッドも一緒に確認できるからです。
しかし、プログラムが少しずつ大きくなると、1つのファイルにすべてのクラスを書き続ける方法では、だんだん見通しが悪くなります。
ドラゴンボール風にたとえると、戦士名簿、修行メニュー、必殺技の記録、戦闘装備の台帳、出撃命令書を、すべて1本の巨大な巻物に書き込んでいるようなものです。
最初は読めても、情報が増えるにつれて、どこに何が書いてあるのか探しにくくなります。
さらに、修正したい場所を見つけるのにも時間がかかります。
そこで大切になるのが、クラスごとにファイルを分ける という考え方です。
クラスごとにファイルを分けると、次のように役割を整理できます。
| ファイル | 役割 |
|---|---|
| SaiyanWarrior.java | サイヤ人戦士の情報を表すクラスを書く |
| Sample1.java | main メソッドを持ち、プログラムを開始する |
SaiyanWarrior.java は、サイヤ人戦士の情報を管理する巻物です。
Sample1.java は、そのサイヤ人戦士を呼び出して処理を始める出撃命令書です。
このように分けることで、どのファイルに何が書かれているのかが分かりやすくなります。
クラスをファイルに分けることは、Javaの動かし方を難しくするためではありません。
クラスの役割を整理し、読みやすく、修正しやすいプログラムにするための工夫です。
クラスをファイルに分けるとは何か
Javaでは、複数のクラスをそれぞれ別のファイルに書けます。
たとえば、サイヤ人戦士の情報を管理するクラスと、プログラムを開始するクラスを分けることができます。
| クラス | ファイル名 | 役割 |
|---|---|---|
| SaiyanWarrior | SaiyanWarrior.java | サイヤ人戦士の名前や流派を管理する |
| Sample1 | Sample1.java | main メソッドを持ち、処理を開始する |
SaiyanWarrior クラスは、サイヤ人戦士の情報を表す部品です。
Sample1 クラスは、プログラムを開始する入口です。
ドラゴンボール風にたとえると、SaiyanWarrior.java は戦士の情報を記録した巻物です。
Sample1.java は、その戦士を作成して確認するための出撃指令書です。
このように分けておくと、役割がとても分かりやすくなります。
| 分け方 | イメージ |
|---|---|
| 1つのファイルに全部書く | すべての情報を1本の巨大な巻物に詰め込む |
| クラスごとにファイルを分ける | 戦士名簿、修行記録、出撃指令を別々の巻物にする |
クラスが増えても、ファイルごとに役割が分かれていれば、整理された状態を保ちやすくなります。
なぜ1つのファイルに全部書かないほうがよいのか
小さいプログラムでは、1つのファイルに全部書いても、それほど困らないことがあります。
しかし、クラスが増えてくると、次のような困りごとが出てきます。
| 困りごと | 1つのファイルにまとめた場合 | ファイルを分けた場合 |
|---|---|---|
| 見つけやすさ | 必要なクラスを探しにくい | 必要なクラスのファイルをすぐ開ける |
| 修正のしやすさ | 関係ない部分まで目に入る | 修正対象に集中しやすい |
| 役割の整理 | どのクラスの仕事か曖昧になりやすい | クラスごとの責任が明確になる |
| 複数人開発 | 同じファイルを同時に触りやすく衝突しやすい | 担当ごとに分担しやすい |
| 再利用 | 一部だけ使い回しにくい | クラス単位で使い回しやすい |
ドラゴンボール風にたとえると、1本の巻物にすべての情報がある状態では、戦士の流派を直したいだけなのに、修行記録や出撃命令、戦闘装備の情報まで目に入ってしまいます。
一方、戦士情報は SaiyanWarrior.java、実行開始は Sample1.java のように分けておけば、必要な巻物だけを開けます。
これは、読みやすさだけでなく、修正のしやすさにもつながります。
図:クラスごとにファイルを分けるイメージ

この図が示していること
この図では、1つの巨大なファイルに複数のクラスを書く場合と、クラスごとにファイルを分ける場合を比較しています。
左側では、すべてのクラスが1本の巻物に詰め込まれています。
この状態では、必要なクラスを探しにくく、修正したい場所も見つけにくくなります。
右側では、クラスごとにファイルが分かれています。
| ファイル | 役割 |
|---|---|
| SaiyanWarrior.java | サイヤ人戦士の情報 |
| TrainingMenu.java | 修行メニュー |
| BattleMission.java | 任務情報 |
| Sample1.java | 実行開始 |
この図から分かることは、ファイルを分けることで、クラスごとの責任がはっきりし、大きなプログラムでも見通しを保ちやすくなるということです。
ドラゴンボール風の例で考える
今回は、サイヤ人戦士を表すクラスとして SaiyanWarrior クラスを使います。
SaiyanWarrior クラスでは、次の情報を管理します。
| 情報 | 内容 |
|---|---|
| name | サイヤ人戦士の名前 |
| style | 流派 |
また、情報を設定するためのメソッドとして setWarrior() を用意します。
情報を表示するためのメソッドとして show() を用意します。
| メソッド | 役割 |
|---|---|
| setWarrior() | 戦士名と流派を設定する |
| show() | 戦士名と流派を表示する |
SaiyanWarrior クラスは、サイヤ人戦士の情報を表す役割を持ちます。
一方、Sample1 クラスは main メソッドを持ち、プログラムを開始する役割を持ちます。
| クラス | 役割 |
|---|---|
| SaiyanWarrior | サイヤ人戦士の情報を管理する |
| Sample1 | SaiyanWarrior オブジェクトを作り、処理を開始する |
このように、クラスごとの役割を分けると、プログラムの構造が分かりやすくなります。
ファイルを分けたときのソースコード
ここでは、2つのファイルに分けて作成します。
1つ目は、サイヤ人戦士の情報を表す SaiyanWarrior.java です。
2つ目は、main メソッドを持つ Sample1.java です。
ファイル名:SaiyanWarrior.java
class SaiyanWarrior
{
private String name;
private String style;
public SaiyanWarrior()
{
name = "未登録";
style = "流派未設定";
System.out.println("サイヤ人戦士を作成しました。");
}
public void setWarrior(String n, String s)
{
name = n;
style = s;
System.out.println("戦士名を" + name + "、流派を" + style + "にしました。");
}
public void show()
{
System.out.println("戦士名は" + name + "です。");
System.out.println("流派は" + style + "です。");
}
}ファイル名:Sample1.java
class Sample1
{
public static void main(String[] args)
{
SaiyanWarrior warrior1 = new SaiyanWarrior();
warrior1.show();
}
}2つのファイルの役割
このプログラムでは、SaiyanWarrior クラスと Sample1 クラスを別々のファイルにしています。
| ファイル名 | クラス名 | 役割 |
|---|---|---|
| SaiyanWarrior.java | SaiyanWarrior | サイヤ人戦士の情報を表す |
| Sample1.java | Sample1 | main メソッドを持ち、処理を開始する |
SaiyanWarrior.java は、サイヤ人戦士の情報を管理するクラスです。
Sample1.java は、SaiyanWarrior オブジェクトを作成して、show() を呼び出す実行用のクラスです。
ここで大切なのは、ファイルを分けても、Sample1.java から SaiyanWarrior クラスを普通に使えていることです。
main メソッドの中では、次の流れで処理しています。
SaiyanWarrior warrior1 = new SaiyanWarrior();
warrior1.show();1行目では、SaiyanWarrior クラスから warrior1 オブジェクトを作成しています。
2行目では、warrior1 の show() を呼び出して、サイヤ人戦士の情報を表示しています。
SaiyanWarrior のコンストラクタでは、次の初期値が設定されています。
| フィールド | 初期値 |
|---|---|
| name | 未登録 |
| style | 流派未設定 |
そのため、show() を呼び出すと、初期状態がそのまま表示されます。
実行結果
サイヤ人戦士を作成しました。
戦士名は未登録です。
流派は流派未設定です。この結果から、SaiyanWarrior オブジェクトが作成され、初期値が表示されていることが分かります。
コンパイルのしかた
クラスを別ファイルに分けても、コンパイルの基本的な考え方は大きく変わりません。
まず、同じフォルダに次の2つのファイルを保存します。
| ファイル | 内容 |
|---|---|
| SaiyanWarrior.java | SaiyanWarrior クラスを書く |
| Sample1.java | Sample1 クラスを書く |
その状態で、Sample1.java をコンパイルします。
PS C:\Java\13>javac Sample1.javaSample1.java の中では SaiyanWarrior クラスを使っています。
そのため、同じフォルダ内に SaiyanWarrior.java があれば、必要に応じて一緒にコンパイルされます。
コンパイル後には、通常、次の class ファイルが作成されます。
| ソースファイル | コンパイル後のファイル |
|---|---|
| SaiyanWarrior.java | SaiyanWarrior.class |
| Sample1.java | Sample1.class |
.java ファイルは、人が読むためのソースファイルです。
.class ファイルは、Javaが実行するためにコンパイルされたファイルです。
ドラゴンボール風にたとえると、.java ファイルは人が読める戦士の巻物です。
.class ファイルは、Javaが実行できる形に変換された戦闘用の符号札のようなものです。
実行のしかた
実行するときは、main メソッドを持っているクラスを指定します。
この例では、main メソッドを持っているのは Sample1 クラスです。
そのため、次のように実行します。
PS C:\Java\13>java Sample1ここで SaiyanWarrior を指定するわけではありません。
SaiyanWarrior クラスには main メソッドがないため、プログラムの開始地点にはなりません。
| クラス | main メソッド | 実行開始クラスにできるか |
|---|---|---|
| SaiyanWarrior | なし | できない |
| Sample1 | あり | できる |
実行時には、Sample1.class だけでなく、Sample1 が利用する SaiyanWarrior.class も必要です。
SaiyanWarrior.class が見つからないと、Sample1 の中で SaiyanWarrior クラスを使えないため、エラーになります。
つまり、ファイルを分けるときは、ソースファイルだけでなく、コンパイル後の class ファイルどうしの関係も意識することが大切です。
なぜファイルを分けても普通に使えるのか
ファイルを分けると、最初は少し不思議に感じるかもしれません。
SaiyanWarrior.java と Sample1.java に分かれているのに、なぜ Sample1 から SaiyanWarrior を普通に使えるのか、気になるところです。
理由は、Javaが最終的に クラス単位 でプログラムを扱うからです。
私たちは、読みやすくするためにソースコードをファイルに分けています。
しかし、Javaにとって大切なのは、必要なクラスが正しく見つかることです。
同じフォルダ内に必要なファイルがそろっていれば、次のような基本操作は変わりません。
| 処理 | 書き方 |
|---|---|
| オブジェクトを作る | new SaiyanWarrior() |
| メソッドを呼び出す | warrior1.show() |
| 実行する | java Sample1 |
つまり、ファイル分割は、プログラムの基本的な使い方を変えるものではありません。
クラスの役割を整理し、読みやすくするための工夫と考えると分かりやすいです。
図:ソースファイルと class ファイルの関係

この図が示していること
この図では、SaiyanWarrior.java と Sample1.java を別々のソースファイルとして作り、それぞれがコンパイルされて class ファイルになる流れを表しています。
左側には .java ファイルがあります。
SaiyanWarrior.java はサイヤ人戦士情報を管理するクラスのファイルです。
Sample1.java は main メソッドを持つ実行開始用のファイルです。
中央では、javac Sample1.java によってコンパイルする流れを示しています。
右側には、コンパイル後の .class ファイルがあります。
| ソースファイル | class ファイル |
|---|---|
| SaiyanWarrior.java | SaiyanWarrior.class |
| Sample1.java | Sample1.class |
実行するときは、main メソッドを持つ Sample1 を指定します。
java Sample1この図から分かることは、ソースファイルを分けても、必要な class ファイルがそろっていれば、クラス同士は連携して動くということです。
大規模なプログラムで重要になる理由
大きなプログラムでは、クラスの数がどんどん増えていきます。
ドラゴンボール風の学習アプリを作るとしても、次のようなクラスが必要になるかもしれません。
| クラス名 | 役割 |
|---|---|
| SaiyanWarrior | サイヤ人戦士の情報を管理する |
| KiTechnique | 気の技を管理する |
| BattleMission | 任務情報を管理する |
| BattleManager | 戦闘の進行を管理する |
| BattleArmor | 戦闘装備の情報を管理する |
| TrainingMenu | 修行メニューを管理する |
これらをすべて1つのファイルに書いてしまうと、読むだけでも大変です。
どこに何があるのか分かりにくくなり、修正したい場所を探すのにも時間がかかります。
ファイルを分けておけば、次のように整理できます。
| 修正したい内容 | 開くファイル |
|---|---|
| サイヤ人戦士の名前や流派を修正したい | SaiyanWarrior.java |
| 気の技を修正したい | KiTechnique.java |
| 任務内容を修正したい | BattleMission.java |
| 戦闘進行を修正したい | BattleManager.java |
| 戦闘装備の情報を修正したい | BattleArmor.java |
ドラゴンボール風にたとえると、戦士名簿、気の技の巻物、出撃任務の指令書、戦闘装備の台帳を別々に管理するようなものです。
必要な巻物だけを開けばよいので、作業がかなり楽になります。
複数人で開発するときにも分担しやすい
ファイル分割は、複数人で開発するときにも役立ちます。
1つの巨大なファイルにすべてのクラスを書いていると、複数人が同じファイルを同時に編集することになります。
すると、作業がぶつかりやすくなります。
| 開発スタイル | 起こりやすいこと |
|---|---|
| 1つのファイルに全部書く | 複数人が同じファイルを触り、衝突しやすい |
| クラスごとにファイルを分ける | 担当ごとに作業しやすい |
たとえば、ある人は SaiyanWarrior.java を担当します。
別の人は BattleMission.java を担当します。
さらに別の人は BattleManager.java を担当します。
このように分ければ、担当範囲がはっきりします。
ドラゴンボール風にたとえると、戦士名簿係、任務管理係、装備管理係が、それぞれ別の巻物を担当するようなものです。
ファイル分割で覚えておきたい考え方
クラスをファイルに分けるときは、次の考え方を押さえておくと理解しやすくなります。
| 覚えておきたいこと | 内容 |
|---|---|
| クラスは別ファイルに書ける | 複数のクラスをそれぞれ分けて管理できる |
| 役割ごとに整理できる | どのファイルが何を担当するか明確になる |
| コンパイル方法は大きく変わらない | 必要なクラスが同じフォルダにあれば扱いやすい |
| 実行は main メソッドを持つクラスを指定する | この例では Sample1 を実行する |
| 大規模開発で重要 | クラス数や担当者が増えても整理しやすい |
特に大切なのは、どのクラスに main メソッドがあるのかを確認することです。
SaiyanWarrior は部品として使われるクラスです。
Sample1 がプログラムの入口です。
この役割を分けて考えると、コンパイルと実行の流れも整理しやすくなります。
学習の段階でつまずきやすい点
初めてクラスを別ファイルに分けると、いくつかつまずきやすいポイントがあります。
| つまずきやすい点 | 内容 | 対策 |
|---|---|---|
| ファイルの保存場所が違う | 同じフォルダにないとクラスが見つからないことがある | まずは同じフォルダに保存する |
| 実行するクラスを間違える | main メソッドを持たないクラスは実行開始できない | main を持つ Sample1 を実行する |
| クラス名の意味が曖昧 | 何の役割か分かりにくい | SaiyanWarrior のように役割が伝わる名前にする |
| 役割が混ざる | データ管理と実行開始が混ざる | SaiyanWarrior と Sample1 のように分ける |
| class ファイルが足りない | 実行時に関連クラスが見つからない | 必要な .class ファイルを同じ場所に置く |
特に大切なのは、実行するクラスを間違えないことです。
SaiyanWarrior は、サイヤ人戦士の情報を表す部品です。
Sample1 は、main メソッドを持つ入口です。
そのため、実行するときは java Sample1 とします。
ファイル名とクラス名の関係
Javaでは、ファイル名とクラス名の関係も意識しておくと安心です。
今回のように、SaiyanWarrior クラスを SaiyanWarrior.java に書くと、対応関係が分かりやすくなります。
| クラス名 | ファイル名 | 分かりやすさ |
|---|---|---|
| SaiyanWarrior | SaiyanWarrior.java | サイヤ人戦士クラスのファイルだと分かりやすい |
| Sample1 | Sample1.java | 実行用クラスのファイルだと分かりやすい |
特に public class を使う場合は、public class の名前とファイル名を一致させる必要があります。
今回の例では class SaiyanWarrior のように public を付けていません。
ただし、学習を進めるうえでは、基本的に クラス名とファイル名をそろえる と考えておくと分かりやすいです。
ドラゴンボール風にたとえると、SaiyanWarrior.java という巻物には、SaiyanWarrior クラスの情報が書かれているほうが自然です。
図:main メソッドを持つクラスを実行する

この図が示していること
この図では、ファイルを分けたときに、どのクラスを実行するのかを表しています。
SaiyanWarrior は、サイヤ人戦士の情報を管理する部品クラスです。
main メソッドを持っていないため、実行開始クラスにはなりません。
Sample1 は、main メソッドを持つ実行用クラスです。
そのため、実行するときは Sample1 を指定します。
| クラス | 役割 | 実行開始できるか |
|---|---|---|
| SaiyanWarrior | 戦士情報を管理する部品 | できない |
| Sample1 | main メソッドを持つ入口 | できる |
この図から分かることは、ファイルを分けたときも、実行時には main メソッドを持つクラスを指定する必要があるということです。
この内容が次の学習につながる理由
クラスをファイルに分けられるようになると、次の学習内容も理解しやすくなります。
| 次に学ぶ内容 | 関係 |
|---|---|
| パッケージ | クラスをさらに大きな単位で整理する |
| 名前空間 | 同じ名前のクラスを区別しやすくする |
| サブパッケージ | 関連するクラスを階層的に整理する |
| インポート | 別の場所にあるクラスを使えるようにする |
これらは、増えてきたクラスをどう整理するかという考え方とつながっています。
まずは、クラスごとにファイルを分ける基本を押さえることが大切です。
ドラゴンボール風にたとえると、最初は戦士名簿を分けるところから始まります。
その次に、サイヤ人部隊の巻物、ナメック星支援部隊の巻物、出撃任務の巻物、装備台帳の巻物をさらに分類していくイメージです。
クラスをファイルに分けるときの大事な感覚
クラスをファイルに分けるときは、次の感覚を持つと分かりやすくなります。
| 考え方 | 内容 |
|---|---|
| 1クラス1役割を意識する | SaiyanWarrior は戦士情報、Sample1 は実行開始 |
| ファイル名で役割が分かるようにする | SaiyanWarrior.java を見れば戦士クラスだと分かる |
| main メソッドの場所を確認する | 実行するのは Sample1 |
| 関連 class ファイルをそろえる | SaiyanWarrior.class と Sample1.class が必要 |
| ファイル分割は整理のための工夫 | 保守しやすさを高める意味が大きい |
クラスをファイルに分けると、Javaのプログラムはぐっと読みやすくなります。
SaiyanWarrior はサイヤ人戦士の情報を担当する。
Sample1 はプログラムの開始を担当する。
このように役割を分けることで、1つひとつのクラスの責任がはっきりします。
そして、この考え方は、パッケージやインポートを学ぶときにもそのままつながっていきます。
