はじめに
Java を使用する際、開発者が最もよく遭遇するフラストレーションの一つが「クラスが見つかりません (class not found)」エラーです。このエラーは、Java 仮想マシン (JVM) がプログラムの実行に必要なクラスを見つけられない場合に発生します。初心者の方でも、Java にある程度の経験がある方でも、このエラーの診断方法と解決方法を理解することは、スムーズな開発のために不可欠です。
この実験 (Lab) では、「クラスが見つかりません (class not found)」エラーの原因、コード内の特定の問題を特定する方法、そしてそれを修正するための効果的な解決策を実装する方法を学びます。このセッションの終わりには、Java プログラミングにおけるこの一般的な障害を克服するための知識と実践的な経験を得ているでしょう。
Java クラスパスとパッケージ構造の理解
エラー自体に入る前に、Java がどのようにクラスを整理し、見つけるのかを理解しましょう。この基礎は、「クラスが見つかりません (class not found)」エラーをより良く診断するのに役立ちます。
Java クラスパス
クラスパスは、Java 仮想マシン (JVM) にクラスとパッケージを探す場所を指示するパラメーターです。Java プログラムを実行すると、JVM は以下の場所でクラスを検索します。
- 現在のディレクトリ
- クラスパスで指定された JAR ファイル
- 標準の Java ライブラリ
簡単な Java プログラムの作成
Java がどのようにコードをコンパイルして実行するのかを理解するために、簡単な Java プログラムを作成しましょう。
WebIDE を開き、
/home/labex/projectディレクトリにHelloWorld.javaという新しいファイルを作成します。ファイルに次のコードを追加します。
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
- ターミナルを開き、プロジェクトディレクトリにいることを確認します。
cd ~/project
javacコマンドを使用して Java プログラムをコンパイルします。
javac HelloWorld.java
javaコマンドを使用してプログラムを実行します。
java HelloWorld
次のような出力が表示されるはずです。
Hello, World!
コンパイルプロセスを理解する
javac コマンドを実行すると、HelloWorld.class というファイルが作成されます。このファイルには、JVM が実行できるバイトコードが含まれています。java コマンドを実行すると、JVM は現在のディレクトリでこのクラスファイルを探し、それを実行します。
この簡単なプログラムの正常な実行は、Java における基本的なコンパイルと実行プロセスを示しています。次に、意図的にエラーを作成して、クラスが見つからない場合に何が起こるかを理解します。
「クラスが見つかりません (Class Not Found)」エラーの発生と理解
Java のコンパイルと実行の基本を理解したところで、意図的に「クラスが見つかりません (class not found)」エラーが発生する状況を作りましょう。これにより、エラーを認識し、その原因を理解するのに役立ちます。
存在しないクラスを持つプログラムの作成
/home/labex/projectディレクトリに、次のコードを含むMainProgram.javaという新しいファイルを作成します。
public class MainProgram {
public static void main(String[] args) {
// まだ存在しないクラスを使用しようとする
Helper helper = new Helper();
helper.doSomething();
}
}
javacコマンドを使用して、このプログラムをコンパイルします。
javac MainProgram.java
次のようなエラーが表示されます。
MainProgram.java:4: error: cannot find symbol
Helper helper = new Helper();
^
symbol: class Helper
location: class MainProgram
このエラーは、Java コンパイラが Helper クラスを見つけられないため、コンパイル時に発生します。不足しているクラスを作成して、これを修正しましょう。
不足しているクラスの作成
- 同じディレクトリに、次のコードを含む
Helper.javaという新しいファイルを作成します。
public class Helper {
public void doSomething() {
System.out.println("Helper is doing something useful!");
}
}
- これで、両方のファイルをコンパイルします。
javac MainProgram.java Helper.java
MainProgramクラスを実行します。
java MainProgram
次のような出力が表示されるはずです。
Helper is doing something useful!
ランタイム「クラスが見つかりません (Class Not Found)」エラーの理解
先ほど遭遇したエラーはコンパイル時のエラーでした。次に、ランタイム「クラスが見つかりません (class not found)」エラーが発生するシナリオを作成しましょう。
- 次のコードを含む
DynamicLoader.javaという新しいファイルを作成します。
public class DynamicLoader {
public static void main(String[] args) {
try {
// 存在しないクラスを動的にロードしようとする
Class.forName("NonExistentClass");
System.out.println("Class loaded successfully!");
} catch (ClassNotFoundException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
- このプログラムをコンパイルして実行します。
javac DynamicLoader.java
java DynamicLoader
次のような出力が表示されるはずです。
Error: NonExistentClass
これは、try-catch ブロックによってキャッチされるランタイム「クラスが見つかりません (class not found)」エラーを示しています。実際のアプリケーションでは、この種のエラーは次のような場合に多く発生します。
- クラスは存在するが、クラスパスにない
- クラス名が誤字または大文字と小文字の区別が間違っている
- クラスはパッケージ内にあるが、パッケージ構造が正しくない
Java パッケージとクラスパスの操作
ほとんどの現実世界の Java アプリケーションは、クラスをパッケージに整理します。この整理は、パッケージ構造が正しく設定されていない場合や、クラスパスが適切に構成されていない場合に、「クラスが見つかりません (class not found)」エラーにつながることがあります。
パッケージ構造の作成
- パッケージのディレクトリ構造を作成します。
mkdir -p ~/project/com/example/util
~/project/com/example/utilディレクトリにStringUtils.javaという新しいファイルを作成します。
package com.example.util;
public class StringUtils {
public static String reverse(String input) {
StringBuilder reversed = new StringBuilder();
for (int i = input.length() - 1; i >= 0; i--) {
reversed.append(input.charAt(i));
}
return reversed.toString();
}
}
ファイルの先頭にある package 宣言に注意してください。これは、このクラスが com.example.util パッケージに属していることを Java に伝えます。
- 次に、
~/projectディレクトリにPackageDemo.javaというファイルを作成します。
import com.example.util.StringUtils;
public class PackageDemo {
public static void main(String[] args) {
String original = "Hello, Java!";
String reversed = StringUtils.reverse(original);
System.out.println("Original: " + original);
System.out.println("Reversed: " + reversed);
}
}
- プロジェクトディレクトリから両方のファイルをコンパイルします。
cd ~/project
javac com/example/util/StringUtils.java
javac PackageDemo.java
PackageDemoクラスを実行します。
java PackageDemo
次のような出力が表示されるはずです。
Original: Hello, Java!
Reversed: !avaJ ,olleH
よくあるパッケージ関連のエラーのトラブルシューティング
トラブルシューティング方法を学ぶために、意図的にいくつかの一般的なエラーを作成しましょう。
エラー 1: 不適切なパッケージディレクトリ構造
- パッケージ宣言がディレクトリ構造と一致しない新しいディレクトリと Java ファイルを作成します。
mkdir -p ~/project/wrong/path
~/project/wrong/pathディレクトリにMisplacedClass.javaというファイルを作成します。
package correct.path;
public class MisplacedClass {
public static void sayHello() {
System.out.println("Hello from MisplacedClass!");
}
}
- このファイルをコンパイルしてみます。
cd ~/project
javac wrong/path/MisplacedClass.java
次のようなエラーが表示されます。
wrong/path/MisplacedClass.java:1: error: package correct.path does not exist
package correct.path;
^
このエラーは、パッケージ宣言 (package correct.path;) がディレクトリ構造 (wrong/path) と一致しないために発生します。
エラー 2: インポート文の欠落
~/projectディレクトリにImportDemo.javaというファイルを作成します。
// Missing import: import com.example.util.StringUtils;
public class ImportDemo {
public static void main(String[] args) {
// StringUtils がインポートされていないため、これがエラーの原因になります
String reversed = StringUtils.reverse("Test");
System.out.println(reversed);
}
}
- このファイルをコンパイルしてみます。
javac ImportDemo.java
次のようなエラーが表示されます。
ImportDemo.java:5: error: cannot find symbol
String reversed = StringUtils.reverse("Test");
^
symbol: variable StringUtils
location: class ImportDemo
このエラーは、StringUtils クラスをインポートしなかったために発生します。これを修正するには、インポート文を追加します。
import com.example.util.StringUtils;
Java のパッケージシステムとクラスパスを正しく理解することは、「クラスが見つかりません (class not found)」エラーを回避し、修正するための基本です。パッケージ宣言がディレクトリ構造と一致し、必要なすべてのクラスが適切にインポートされていることを常に確認してください。
外部 JAR ファイルの使用とクラスパスの設定
多くの Java アプリケーションは、JAR (Java ARchive) ファイルとして配布される外部ライブラリに依存しています。これらの JAR ファイルがクラスパスに適切に含まれていない場合、これらのライブラリのクラスを使用しようとすると、「クラスが見つかりません (class not found)」エラーが発生します。
カスタム JAR ファイルの作成
外部ライブラリがどのように機能するかを理解するために、簡単な JAR ファイルを作成しましょう。
- まず、先ほど作成した
StringUtilsクラスをコンパイルします。
cd ~/project
javac com/example/util/StringUtils.java
- このクラスを含む JAR ファイルを作成します。
jar cf utils.jar com/example/util/StringUtils.class
- JAR ファイルが作成されたことを確認します。
ls -l utils.jar
次のような出力が表示されるはずです。
-rw-r--r-- 1 labex labex 1234 Jan 1 12:34 utils.jar
- 次に、この JAR ファイルを使用する新しいプログラムを作成しましょう。
~/projectディレクトリにJarDemo.javaというファイルを作成します。
public class JarDemo {
public static void main(String[] args) {
try {
// JAR ファイルからクラスを使用しようとする
Class<?> clazz = Class.forName("com.example.util.StringUtils");
System.out.println("Successfully loaded: " + clazz.getName());
} catch (ClassNotFoundException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
- このプログラムをコンパイルします。
javac JarDemo.java
- クラスパスを指定せずにプログラムを実行します。
java JarDemo
次のような出力が表示されるはずです。
Error: com.example.util.StringUtils
これは、「クラスが見つかりません (class not found)」エラーです。JVM が StringUtils クラスを見つけられないためです。クラスは JAR ファイルにありますが、JVM にどこを探せばよいかを指示していません。
クラスパスの設定
エラーを修正するには、JAR ファイルをクラスパスに含める必要があります。
-classpathオプションを使用してプログラムを実行します。
java -classpath .:utils.jar JarDemo
これで、次のような出力が表示されるはずです。
Successfully loaded: com.example.util.StringUtils
クラスパスの構文を分解してみましょう。
.は、現在のディレクトリを意味します (JarDemo.classを見つけるため):は、Linux/Mac 上の異なるクラスパスエントリの区切り文字です (Windows では;を使用します)utils.jarは、JAR ファイルです
外部ライブラリの使用
パブリック Maven リポジトリから外部ライブラリを使用してみましょう。
- 簡単で軽量な JSON ライブラリをダウンロードします。
cd ~/project
wget https://repo1.maven.org/maven2/org/json/json/20230618/json-20230618.jar
- このライブラリを使用するプログラムを作成します。
JsonDemo.javaというファイルを作成します。
import org.json.JSONObject;
public class JsonDemo {
public static void main(String[] args) {
// JSON オブジェクトを作成する
JSONObject json = new JSONObject();
json.put("name", "Java Student");
json.put("age", 25);
json.put("city", "Codeville");
// JSON オブジェクトを出力する
System.out.println(json.toString(2));
}
}
- クラスパスに JSON ライブラリを含めて、このプログラムをコンパイルします。
javac -classpath .:json-20230618.jar JsonDemo.java
- クラスパスに JSON ライブラリを含めて、プログラムを実行します。
java -classpath .:json-20230618.jar JsonDemo
次のような出力が表示されるはずです。
{
"name": "Java Student",
"age": 25,
"city": "Codeville"
}
CLASSPATH 環境変数の設定
各コマンドでクラスパスを指定する代わりに、CLASSPATH 環境変数を設定できます。
export CLASSPATH=.:utils.jar:json-20230618.jar
これで、クラスパスを指定せずにプログラムを実行できます。
java JsonDemo
これは、以前と同じ出力を生成するはずです。
CLASSPATH 環境変数を使用する場合は、次の点に注意してください。
- 現在のシェルセッションで実行されるすべての Java プログラムに影響します
- コマンドラインで
-classpathを指定すると、上書きされます - ターミナルを閉じると設定は失われます (起動スクリプトに追加しない限り)
外部ライブラリを適切に使用し、クラスパスを設定する方法を理解することは、現実世界の Java アプリケーションで「クラスが見つかりません (class not found)」エラーを回避するために不可欠です。
よくある「クラスが見つかりません (Class Not Found)」のシナリオと解決策
Java クラスパスとパッケージシステムの基本を理解したところで、「クラスが見つかりません (class not found)」エラーにつながるいくつかの一般的なシナリオと、それらを解決する方法を探ってみましょう。
シナリオ 1: クラス名のタイプミス
「クラスが見つかりません (class not found)」エラーの最も一般的な原因の 1 つは、単にクラス名をスペルミスすることです。これを実演してみましょう。
~/projectディレクトリにTypoDemo.javaというファイルを作成します。
import java.util.Scanner; // 正しいインポート
// import java.util.scanner; // 間違ったインポート (小文字の 's')
public class TypoDemo {
public static void main(String[] args) {
// Scanner scanner = new scanner(System.in); // 間違い (小文字の 's')
Scanner scanner = new Scanner(System.in); // 正しい
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.println("Hello, " + name + "!");
scanner.close();
}
}
- このプログラムをコンパイルして実行します。
javac TypoDemo.java
java TypoDemo
- プロンプトが表示されたら、名前を入力して Enter キーを押します。挨拶が表示されるはずです。
間違ったインポートのコメントを外し、正しいインポートをコメントアウトすると、コンパイル時のエラーが発生します。Java では大文字と小文字が区別されるため、Scanner と scanner は異なるクラスです。
シナリオ 2: 依存クラスのコンパイル忘れ
もう 1 つの一般的なシナリオは、変更を加えた後に依存クラスを再コンパイルし忘れることです。
- 先ほど作成した
Helper.javaファイルを更新します。
public class Helper {
public void doSomething() {
System.out.println("Helper is doing something useful!");
}
// 新しいメソッドを追加する
public void doSomethingElse() {
System.out.println("Helper is doing something else!");
}
}
DependencyDemo.javaという新しいファイルを作成します。
public class DependencyDemo {
public static void main(String[] args) {
Helper helper = new Helper();
helper.doSomething();
helper.doSomethingElse();
}
}
- これらのファイルをコンパイルして実行します。
javac Helper.java
javac DependencyDemo.java
java DependencyDemo
Helper クラスからの両方のメッセージが表示されるはずです。
- さて、変更後に再コンパイルしないとどうなるか見てみましょう。
Helper.javaをもう一度更新します。
public class Helper {
public void doSomething() {
System.out.println("Helper is doing something useful!");
}
public void doSomethingElse() {
System.out.println("Helper is doing something else!");
}
// もう 1 つの新しいメソッドを追加する
public void doAnotherThing() {
System.out.println("Helper is doing another thing!");
}
}
Helper.javaを再コンパイルせずに、DependencyDemo.javaを更新します。
public class DependencyDemo {
public static void main(String[] args) {
Helper helper = new Helper();
helper.doSomething();
helper.doSomethingElse();
helper.doAnotherThing(); // これがエラーの原因になります
}
}
- コンパイルして実行してみます。
javac DependencyDemo.java
java DependencyDemo
doAnotherThing() メソッドを Helper クラスに追加したにもかかわらず、コンパイル時のエラーが発生し、doAnotherThing() メソッドが存在しないと表示されます。これは、変更を加えた後に Helper.java を再コンパイルしなかったためです。
- これを修正するには、両方のファイルを再コンパイルします。
javac Helper.java
javac DependencyDemo.java
java DependencyDemo
これで、すべてが正しく動作するはずです。
シナリオ 3: JDBC ドライバーの欠落
現実世界のアプリケーションでよくある「クラスが見つかりません (class not found)」エラーには、データベース接続が含まれます。JDBC (Java Database Connectivity) を使用する場合は、データベースに適したドライバーが必要です。これをシミュレートしてみましょう。
JdbcDemo.javaというファイルを作成します。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JdbcDemo {
public static void main(String[] args) {
try {
// これが ClassNotFoundException の原因になります
Class.forName("com.mysql.jdbc.Driver");
// この例では、実際にデータベースに接続しません
System.out.println("Driver loaded successfully!");
// 実際のアプリケーションでは、次のように接続します。
// Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password");
} catch (ClassNotFoundException e) {
System.out.println("Error: JDBC Driver not found - " + e.getMessage());
System.out.println("Solution: Add the MySQL JDBC driver to your classpath");
}
}
}
- このプログラムをコンパイルして実行します。
javac JdbcDemo.java
java JdbcDemo
次のようなエラーメッセージが表示されるはずです。
Error: JDBC Driver not found - com.mysql.jdbc.Driver
Solution: Add the MySQL JDBC driver to your classpath
実際のアプリケーションでは、適切な JDBC ドライバー JAR ファイルをダウンロードし、それをクラスパスに追加する必要があります。
解決策のまとめ
「クラスが見つかりません (class not found)」エラーを解決するためのクイックリファレンスガイドを次に示します。
- スペルと大文字/小文字を確認する: Java では大文字と小文字が区別されます。
- パッケージ構造を確認する: パッケージがディレクトリ構造と一致していることを確認します。
- 依存クラスを再コンパイルする: クラスに変更を加えた後、そのクラスとすべての依存クラスを再コンパイルします。
- クラスパスを正しく設定する: 必要なすべてのディレクトリと JAR ファイルを含めます。
- IDE を使用する: IntelliJ IDEA や Eclipse などの最新の IDE は、これらのタスクの多くを自動化します。
- ビルドツールを使用する: Maven または Gradle は、依存関係を管理できます。
これらの一般的なシナリオとその解決策を理解することで、Java アプリケーションで「クラスが見つかりません (class not found)」エラーを診断して修正するための十分な準備ができます。
まとめ
この実験 (Lab) では、Java でよくある「クラスが見つかりません (class not found)」エラーを診断し、解決する方法を学びました。以下のことを理解できるようになりました。
- Java クラスパスの仕組みとその重要性
- Java パッケージ構造とディレクトリ構造の関係
- 「クラスが見つかりません (class not found)」エラーの一般的な原因。これには以下が含まれます。
- クラス名のタイプミス
- インポート文の欠落
- 不適切なパッケージ宣言
- 依存クラスの再コンパイル忘れ
- クラスパス内の JAR ファイルの欠落
また、これらの問題に対する実用的な解決策も学びました。
-classpathオプションを使用したクラスパスの設定CLASSPATH環境変数の使用- JAR ファイルと外部ライブラリの操作
- Java パッケージの適切な整理
この知識があれば、Java アプリケーションで「クラスが見つかりません (class not found)」エラーを自信を持ってトラブルシューティングし、解決できるようになり、開発中の時間を節約し、フラストレーションを軽減できます。
Java 開発に習熟するには、練習が重要であることを忘れないでください。より複雑なプロジェクトを作成し、意図的にさまざまな種類のエラーを導入して、デバッグスキルを向上させてください。



