'cannot access class'エラーの解決方法

JavaBeginner
オンラインで実践に進む

はじめに

Java プログラミングにおいて、「cannot access class(クラスにアクセスできません)」エラーは、開発者がよく遭遇する一般的なチャレンジです。このエラーは、様々な理由で、コードがアクセスできないクラスを使用しようとした場合に発生します。このエラーを理解することは、効果的な Java アプリケーションを作成するために不可欠です。

この実践的な実験(Lab)では、「cannot access class(クラスにアクセスできません)」エラーの根本原因を学び、それを解決するための実践的なソリューションを実装します。実際の例を通して作業することで、Java コードのアクセシビリティ問題を診断し、修正するための貴重なスキルを習得できます。

「cannot access class(クラスにアクセスできません)」エラーが発生する Java プロジェクトの作成

このステップでは、Java プロジェクト構造を作成し、実際の「cannot access class(クラスにアクセスできません)」エラーに遭遇します。これにより、エラーが実際にどのように発生するのかを理解できます。

プロジェクト構造の設定

まず、ターミナルで次のコマンドを実行して、プロジェクトディレクトリにいることを確認します。

pwd

次のような出力が表示されるはずです。

/home/labex/project

セットアップスクリプトは、すでに基本的な Java プロジェクト構造を作成しています。次のコマンドを使用して、それを調べてみましょう。

ls -la

次のような出力が表示されるはずです。

total 12
drwxr-xr-x 4 labex labex 4096 May  5 10:00 .
drwxr-xr-x 5 labex labex 4096 May  5 10:00 ..
drwxr-xr-x 2 labex labex 4096 May  5 10:00 bin
-rwxr-xr-x 1 labex labex  105 May  5 10:00 compile.sh
-rwxr-xr-x 1 labex labex   64 May  5 10:00 run.sh
drwxr-xr-x 3 labex labex 4096 May  5 10:00 src

Java クラスの作成

次に、「cannot access class(クラスにアクセスできません)」エラーを実証する 2 つの Java クラスを作成しましょう。

まず、com.example.utilパッケージにHelperクラスを作成します。WebIDE ファイルエクスプローラーでそれに移動するか、次のコマンドを使用してファイルを開きます。

mkdir -p src/main/java/com/example/util

WebIDE で、src/main/java/com/example/utilに移動し、Helper.javaという名前の新しいファイルを作成します。次のコードを追加します。

package com.example.util;

class Helper {
    public void helperMethod() {
        System.out.println("This is a helper method.");
    }
}

このクラスにはデフォルト(パッケージプライベート)のアクセス修飾子があることに注意してください。これは、同じパッケージ内からのみアクセスできることを意味します。

次に、HelperクラスにアクセスしようとするMainクラスをcom.example.appパッケージに作成します。WebIDE でsrc/main/java/com/example/appに移動し、Main.javaという名前の新しいファイルを作成します。次のコードを追加します。

package com.example.app;

import com.example.util.Helper;

public class Main {
    public static void main(String[] args) {
        System.out.println("Attempting to access the Helper class...");

        // Try to create an instance of the Helper class
        Helper helper = new Helper();
        helper.helperMethod();

        System.out.println("Successfully accessed the Helper class!");
    }
}

コンパイルとエラーの観察

次に、提供されているスクリプトを使用して Java プロジェクトをコンパイルしてみましょう。

./compile.sh

次のようなエラーメッセージが表示されるはずです。

src/main/java/com/example/app/Main.java:3: error: cannot access Helper
import com.example.util.Helper;
                      ^
  class file for com.example.util.Helper not found
src/main/java/com/example/app/Main.java:9: error: cannot find symbol
        Helper helper = new Helper();
        ^
  symbol:   class Helper
  location: class Main
src/main/java/com/example/app/Main.java:9: error: cannot find symbol
        Helper helper = new Helper();
                            ^
  symbol:   class Helper
  location: class Main
3 errors

これが「cannot access class(クラスにアクセスできません)」エラーです。Helperクラスを作成したにもかかわらず、Mainクラスはそれにアクセスできません。これは、Helperクラスがデフォルトのアクセス修飾子を持っているため、独自のパッケージ内でのみアクセス可能になっているためです。

次のステップでは、この種の問題を特定し、解決する方法を学びます。

アクセス修飾子の問題の理解と解決

前のステップでは、Helperクラスがデフォルト(パッケージプライベート)アクセスを持っていたため、「cannot access class(クラスにアクセスできません)」エラーが発生しました。Java のアクセス修飾子を理解し、この問題を解決しましょう。

Java のアクセス修飾子の理解

Java には、4 種類のアクセス修飾子があります。

  1. private: 同じクラス内でのみアクセス可能
  2. default(修飾子なし): 同じパッケージ内でのみアクセス可能
  3. protected: 同じパッケージ内およびサブクラスからアクセス可能
  4. public: どこからでもアクセス可能

この場合、Helperクラスはデフォルトのアクセス修飾子を持っています。これは、com.example.utilパッケージ内からのみアクセスできることを意味します。Mainクラスはcom.example.appパッケージにあるため、Helperクラスにアクセスできません。

アクセス修飾子の問題の修正

この問題を解決するには、Helperクラスのアクセス修飾子をデフォルトから public に変更する必要があります。WebIDE でHelper.javaファイルを開き、次のように修正します。

package com.example.util;

public class Helper {
    public void helperMethod() {
        System.out.println("This is a helper method.");
    }
}

class宣言の前にpublicキーワードが追加されていることに注意してください。これにより、Helperクラスはどのパッケージからもアクセスできるようになります。

再コンパイルとソリューションのテスト

次に、Java プロジェクトを再コンパイルします。

./compile.sh

コンパイルが成功した場合、エラーメッセージは表示されません。アプリケーションを実行して、正しく動作することを確認しましょう。

./run.sh

次のような出力が表示されるはずです。

Attempting to access the Helper class...
This is a helper method.
Successfully accessed the Helper class!

この出力は、MainクラスがHelperクラスにアクセスし、そのメソッドを呼び出すことができるようになったことを確認しています。

ソリューションの理解

Helperクラスのアクセス修飾子をデフォルトから public に変更することにより、com.example.appパッケージを含む、どのパッケージからもアクセスできるようにしました。

これは、別のパッケージからクラスにアクセスする必要がある場合の「cannot access class(クラスにアクセスできません)」エラーに対する一般的な解決策です。クラスをそのパッケージ外からアクセス可能にするには、publicとして宣言する必要があることを覚えておいてください。

次のステップでは、「cannot access class(クラスにアクセスできません)」エラーのもう 1 つの一般的な原因である、不適切なパッケージ構造について学びます。

パッケージ構造の問題の解決

「cannot access class(クラスにアクセスできません)」エラーのもう 1 つの一般的な原因は、不適切なパッケージ構造です。このステップでは、Java でパッケージ構造の問題を特定し、解決する方法を学びます。

Java におけるパッケージ構造の理解

Java では、パッケージ構造はディレクトリ構造と一致する必要があります。たとえば、com.example.utilパッケージ内のクラスは、com/example/utilディレクトリに配置する必要があります。

物理的なディレクトリ構造がパッケージ宣言と一致しない場合、アクセス修飾子が正しくても、「cannot access class(クラスにアクセスできません)」エラーが発生します。

パッケージ構造の問題があるクラスの作成

この問題を実証するために、パッケージ宣言が正しくない新しい Java クラスを作成しましょう。src/main/java/com/example/utilディレクトリに、次の内容でLogger.javaという名前の新しいファイルを作成します。

package com.example.logger; // Incorrect package declaration

public class Logger {
    public void log(String message) {
        System.out.println("LOG: " + message);
    }
}

パッケージ宣言はcom.example.loggerですが、ファイルはcom/example/utilディレクトリに配置されていることに注意してください。この不一致により、「cannot access class(クラスにアクセスできません)」エラーが発生します。

次に、Loggerクラスを使用しようとするsrc/main/java/com/example/appディレクトリに、LogTest.javaという名前の新しいファイルを作成します。

package com.example.app;

import com.example.logger.Logger;

public class LogTest {
    public static void main(String[] args) {
        Logger logger = new Logger();
        logger.log("Testing logger");
    }
}

コンパイルとエラーの観察

Java プロジェクトをコンパイルしてみましょう。

./compile.sh

次のようなエラーメッセージが表示されるはずです。

src/main/java/com/example/app/LogTest.java:3: error: package com.example.logger does not exist
import com.example.logger.Logger;
                        ^
src/main/java/com/example/app/LogTest.java:6: error: cannot find symbol
        Logger logger = new Logger();
        ^
  symbol:   class Logger
  location: class LogTest
src/main/java/com/example/app/LogTest.java:6: error: cannot find symbol
        Logger logger = new Logger();
                            ^
  symbol:   class Logger
  location: class LogTest
3 errors

このエラーは、コンパイラがcom.example.loggerパッケージ内でLoggerクラスを見つけられないために発生します。これは、そのようなパッケージがないか、ディレクトリ構造がパッケージ宣言と一致しないためです。

パッケージ構造の問題の修正

この問題を修正するには、2 つの方法があります。

  1. パッケージ宣言をディレクトリ構造と一致するように変更する
  2. ファイルをパッケージ宣言と一致するディレクトリ構造に移動する

最初の方法を使用しましょう。Logger.javaファイルを開き、パッケージ宣言をディレクトリ構造と一致するように修正します。

package com.example.util; // Correct package declaration

public class Logger {
    public void log(String message) {
        System.out.println("LOG: " + message);
    }
}

また、LogTest.javaファイルの import 文を更新します。

package com.example.app;

import com.example.util.Logger; // Updated import

public class LogTest {
    public static void main(String[] args) {
        Logger logger = new Logger();
        logger.log("Testing logger");
    }
}

再コンパイルとソリューションのテスト

次に、Java プロジェクトを再コンパイルします。

./compile.sh

コンパイルは、エラーなしで成功するはずです。LogTestクラスを実行する簡単なスクリプトを作成しましょう。

echo "java -cp bin com.example.app.LogTest" > ./runlog.sh
chmod +x ./runlog.sh

次に、LogTestクラスを実行します。

./runlog.sh

次のような出力が表示されるはずです。

LOG: Testing logger

これは、パッケージ宣言がディレクトリ構造と一致しているため、LogTestクラスがLoggerクラスにアクセスできるようになったことを確認しています。

ソリューションの理解

「cannot access class(クラスにアクセスできません)」エラーが発生した場合は、常に以下を確認してください。

  1. ソースファイルのパッケージ宣言がディレクトリ構造と一致していること
  2. import 文が、クラスが配置されているパッケージを正しく参照していること

これら 2 つの条件が満たされていることを確認することで、Java プロジェクトで多くの「cannot access class(クラスにアクセスできません)」エラーを回避できます。

インポート文の問題の処理

この最終ステップでは、不足している、または間違ったインポート文が原因で発生する「cannot access class(クラスにアクセスできません)」エラーを特定し、解決する方法を学びます。

Java におけるインポート文の理解

インポート文は、Java コンパイラに、コードで使用されているクラスを見つける場所を指示します。他のパッケージのクラスをインポートせずに使用した場合、または誤ってインポートした場合は、「cannot access class(クラスにアクセスできません)」エラーが発生します。

インポート文なしでクラスを作成する

適切なインポート文なしで、他のパッケージのクラスを使用するクラスを作成しましょう。src/main/java/com/example/utilディレクトリに、次の内容でCalculator.javaという名前の新しいファイルを作成します。

package com.example.util;

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

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

次に、Calculatorクラスをインポートせずに使用するsrc/main/java/com/example/appディレクトリに、CalculatorDemo.javaという名前の新しいファイルを作成します。

package com.example.app;

// Missing import for Calculator class

public class CalculatorDemo {
    public static void main(String[] args) {
        Calculator calculator = new Calculator(); // Error: Cannot access Calculator

        int sum = calculator.add(5, 3);
        System.out.println("5 + 3 = " + sum);

        int difference = calculator.subtract(10, 4);
        System.out.println("10 - 4 = " + difference);
    }
}

コンパイルとエラーの観察

Java プロジェクトをコンパイルしてみましょう。

./compile.sh

次のようなエラーメッセージが表示されるはずです。

src/main/java/com/example/app/CalculatorDemo.java:6: error: cannot find symbol
        Calculator calculator = new Calculator();
        ^
  symbol:   class Calculator
  location: class CalculatorDemo
src/main/java/com/example/app/CalculatorDemo.java:6: error: cannot find symbol
        Calculator calculator = new Calculator();
                                    ^
  symbol:   class Calculator
  location: class CalculatorDemo
2 errors

このエラーは、CalculatorDemoクラスがCalculatorクラスをインポートせずに使用しようとしているために発生します。

インポート文の問題の修正

この問題を解決するには、CalculatorDemo.javaファイルに適切なインポート文を追加します。

package com.example.app;

import com.example.util.Calculator; // Added import statement

public class CalculatorDemo {
    public static void main(String[] args) {
        Calculator calculator = new Calculator();

        int sum = calculator.add(5, 3);
        System.out.println("5 + 3 = " + sum);

        int difference = calculator.subtract(10, 4);
        System.out.println("10 - 4 = " + difference);
    }
}

再コンパイルとソリューションのテスト

次に、Java プロジェクトを再コンパイルします。

./compile.sh

コンパイルは、エラーなしで成功するはずです。CalculatorDemoクラスを実行する簡単なスクリプトを作成しましょう。

echo "java -cp bin com.example.app.CalculatorDemo" > ./runcalc.sh
chmod +x ./runcalc.sh

次に、CalculatorDemoクラスを実行します。

./runcalc.sh

次のような出力が表示されるはずです。

5 + 3 = 8
10 - 4 = 6

これは、正しいインポート文を追加したため、CalculatorDemoクラスがCalculatorクラスにアクセスできるようになったことを確認しています。

ソリューションの理解

「cannot access class(クラスにアクセスできません)」エラーが発生した場合は、以下を確認してください。

  1. 使用しようとしているクラスをインポートしたこと
  2. インポート文が正しいパッケージを指していること
  3. インポートしようとしているクラスが public であること(ステップ 2 で学習しました)

Java には、クラスをインポートする方法が 2 つあります。

  1. 単一型インポート: import com.example.util.Calculator;
  2. オンデマンドインポート: import com.example.util.*;

単一型インポートは、どのクラスが使用されているかを明確にするため、一般的に推奨されます。オンデマンドインポート(ワイルドカード*を使用)は、パッケージ内のすべてのクラスをインポートします。これは、同じ名前のクラスが異なるパッケージに存在する場合、名前の競合につながる可能性があります。

インポート文が正しいことを確認することで、Java プロジェクトで多くの「cannot access class(クラスにアクセスできません)」エラーを回避できます。

まとめ

この実験では、Java で「cannot access class(クラスにアクセスできません)」エラーを特定し、解決する方法を学びました。このエラーの 3 つの主な原因を理解しました。

  1. アクセス修飾子の問題: クラスが適切なアクセス修飾子で宣言されていない場合、特定の場所からアクセスできません。クラスをpublicにすると、どのパッケージからもアクセスできるようになります。

  2. パッケージ構造の問題: Java ファイルのパッケージ宣言は、ディレクトリ構造と一致する必要があります。不一致があると、コンパイラはクラスを見つけることができず、「cannot access class(クラスにアクセスできません)」エラーが発生します。

  3. インポート文の問題: 他のパッケージのクラスは、import文を使用して適切にインポートする必要があります。インポート文の欠落または誤りは、「cannot access class(クラスにアクセスできません)」エラーにつながります。

これらの原因とその解決策を理解することで、Java プロジェクトで「cannot access class(クラスにアクセスできません)」エラーを効果的に診断し、解決できます。この知識は、時間を節約し、より堅牢で保守性の高い Java コードを作成するのに役立ちます。