本ページはプロモーションが含まれています

Java入門

Java「シンボルを見つけられません」原因7つと解決コード例

CATEGORY
REV.
DRAWN BY
TOM
SHEETS
6枚
cannot find symbol(原因7つと解決コード例)

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

Javaで「シンボルを見つけられません(error: cannot find symbol)」が出たら、下の早見表で30秒で原因を特定できます。

エラーメッセージの symbol: 行が class / method / variable のどれかを見てください。それだけで7つの原因パターンを絞り込めます。

各パターンにはコピペで使える修正コードを用意しました。初めてこのエラーに遭遇した方でも、該当箇所を差し替えるだけで解決できます。

スペルミス・import忘れ・スコープ外アクセスといった基本原因から、Maven/Gradleの依存関係エラーやJavaバージョン不一致まで網羅しています。

  • エラーメッセージから原因を30秒で特定する方法
  • スペルミス・import忘れ・スコープ・自作クラス・外部ライブラリなど7パターンの解決コード
  • 同一パッケージ内・Maven/Gradleで発生する特殊ケースへの対処法

私自身、Java開発のキャリアをスタートさせた当初、このエラーに何度も遭遇していました。

特に多かったのがスコープ外での変数参照とimport忘れで、同じミスを繰り返しては先輩に「エラーメッセージをよく読め」と言われたものです。

この記事のパターンを押さえてからは、エラーメッセージの symbol 行を見るだけで原因を即特定できるようになりました。

解決にかかる時間も数分から数十秒に短縮されています。

PARTS LIST /目次

今すぐ解決したい方へ:エラーの原因と対処法まとめ

cannot find symbol エラーの原因は、ほぼ次の表に絞られます。

原因具体例対処法
スペル・大文字小文字の間違いString を string と小文字で書いている正しいスペルに修正する
import 文の不足Scanner を使うのに import java.util.Scanner; を書いていないファイル先頭に import 文を追加する
変数の宣言忘れ・スコープ外での使用for文の中で宣言した変数をループの外で使おうとしている変数の宣言位置を使いたい場所に合わせて調整する
new の書き忘れMyClass obj = MyClass(); のようにインスタンス生成で new を付けていないnew MyClass() と書く
自作クラス・同一パッケージのパッケージ設定ミス別ファイルで定義した自作クラスに package 宣言が設定されていない・食い違っている両ファイルのパッケージ宣言を揃えるか import 文を追加する
外部ライブラリ(JAR / Maven / Gradle)の不足pom.xml や build.gradle にライブラリの依存関係を追加し忘れている依存関係を追加しビルドツールを再実行する
ビルド環境の不一致Lombok のアノテーションプロセッサが未設定・Java のバージョンが合っていないアノテーションプロセッサを設定する・Java のバージョンを揃える

確認するのはエラーメッセージの symbol: 行だけです。

class / method / variable のどれかがわかれば、上の表のどの原因かをすぐに特定できます。

詳しい解説とコード例は、以降の各ケース別セクションで順番に説明します。

Javaで「cannot find symbol」が出るのはなぜ?

cannot find symbolエラーは、Javaコンパイラがソースコードを読み込む途中で、コードに書いた「名前」を見つけられなかったときに発生します。

コンパイラはプログラムを上から順に読み込み、知らない単語が出てくると「これは何?」と立ち止まってしまいます。

この「見つけられない名前」のことをJavaの世界では「シンボル」と呼びます。

「シンボルが見つかりません」と覚えている方もいますが、javac の日本語メッセージは正確には「エラー: シンボルを見つけられません」です。英語環境の error: cannot find symbol と同じエラーなので、対処法も共通です。

本記事のコード例は Java 21 LTS で動作確認しています。

Java 8 / 11 / 17 / 25 でも同じ現象で発生するため、どのバージョンでも対処法は共通です。

エラーメッセージの意味を理解しよう

エラーメッセージは、解決のための最大のヒントです。cannot find symbol というメッセージが表示されたら、慌てずにその続きを読みます。

Sample.java:10: error: cannot find symbol
    System.out.printin("Hello, World!");
              ^
  symbol:   method printin(String)
  location: variable out of type PrintStream

エラーメッセージは、以下のような情報を教えてくれています。

ポイント

  • ファイルと行数: Sample.java:10 → Sample.java ファイルの10行目でエラー
  • エラー箇所: ^ の記号が、問題となっているメソッド呼び出しの .printin のドットの位置を指す
  • 見つからないシンボルの種類: symbol: method printin(String) → printin という名前のメソッドが見つからない
  • 探した場所: location: variable out of type PrintStream → PrintStream 型の out という変数の中を探したけど見つからない

ファイル名・行番号・symbol種別・locationの4点をエラーメッセージから読み取れば、7つの原因パターンのうちどれに該当するかをほぼ確定できます。

エラーメッセージの4点を上から順に読む

MESSAGE / エラーメッセージの各行

1Sample.java:10: error: cannot find symbolファイルと行数:Sample.java の10行目
2System.out.printin("Hello, World!"); と下の ^エラー箇所:^ が .printin のドットの位置を指す
3symbol: method printin(String)種類:printin という「メソッド」が見つからない
4location: variable out of type PrintStream探した場所:PrintStream 型の変数 out の中
NOTE上のエラーメッセージ例と同じ内容です。3 の symbol 行(class / method / variable)で、原因の種類が決まります。

よくある原因(クラス・メソッド・変数が見つからない)

「シンボルを見つけられません」エラーの原因は、クラス・メソッド・変数の3分類に絞れます。以下のいずれかに該当することがほとんどです。

ポイント

  1. クラスが見つからない: String や Scanner のような、「クラス」の名前を間違えている、または読み込むのを忘れている
  2. メソッドが見つからない: println のような、「メソッド」の名前や使い方を間違えている
  3. 変数が見つからない: 「変数」の名前を間違えている、または使える範囲外で使おうとしている

クラス・メソッド・変数の3分類を理解するだけで、エラー解決のスピードは格段に上がります。

「cannot find symbol」エラーの原因と対処法【ケース別】

symbol: 行の種類から原因を絞る切り分け表
SYMBOL / 種類
確認1
確認2(確認1が「いいえ」のとき)
classクラス名を確認
スペルミス?はい → 修正する
import文はある?ない → import文を追加
ある → 依存関係を確認
methodメソッド名を確認
スペルミス?はい → 修正する
メソッドの存在・所属クラスを確認引数が合わないだけなら別エラー
variable変数名を確認
スペルミス?はい → 修正する
宣言済み?いいえ → 宣言を追加
はい → スコープを確認
NOTEエラーが出たら、まずエラーメッセージの symbol: 行で種類を見ます。どの行き先も、対処すれば解決に行き着きます。

図で当たりを付けたら、該当するケースの修正コードへ進んでください。

クラスが見つからない(symbol: class)場合の解決方法

クラスが見つからない場合、主に「スペルミス」と「import文の不足」が原因です。

原因1:クラス名のスペルミス

Javaでは、大文字と小文字が厳密に区別されます。

例えば、文字列を扱う String クラスを string と小文字で書いたとします。

コンパイラは string という名前のクラスを探しますが、見つからずにエラーを出します。

悪い例:
public class Main {
    public static void main(String[] args) {
        string message = "こんにちは"; // ← "String" の "S" が小文字になっている
        System.out.println(message);
    }
}
エラーメッセージ:
Main.java:3: error: cannot find symbol
        string message = "こんにちは";
        ^
  symbol:   class string
  location: class Main
良い例:

クラス名を正しい表記に修正します。string を String に直せば、正しくコンパイルが通ります。

public class Main {
    public static void main(String[] args) {
        String message = "こんにちは"; // ← 正しく大文字の "S" に修正
        System.out.println(message);
    }
}

原因2:import文の不足

Javaには、便利な機能があらかじめ「ライブラリ」として用意されています。キーボードからの入力を受け付ける Scanner クラスなどが代表例です。

ライブラリのクラスを使うには、プログラムの冒頭で「このクラスを使います」という宣言(import文)が必要です。

悪い例:
// import文が不足している
public class UserInput {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in); // ← Scannerクラスを使おうとしている
        System.out.println("名前を入力してください:");
        String name = scanner.nextLine();
        System.out.println("こんにちは、" + name + "さん");
    }
}
エラーメッセージ:
UserInput.java:4: error: cannot find symbol
        Scanner scanner = new Scanner(System.in);
        ^
  symbol:   class Scanner
  location: class UserInput
(同じエラーが new Scanner の位置にも出て、合計 2 errors になります)
良い例:

ファイルの先頭(public class の前)に、使用するクラスの import 文を記述します。

Scanner クラスの場合は import java.util.Scanner; と書きます。

import java.util.Scanner; // ← import文を追加

public class UserInput {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("名前を入力してください:");
        String name = scanner.nextLine();
        System.out.println("こんにちは、" + name + "さん");
    }
}

同じパッケージに属するクラスを複数使いたい場合は、アスタリスク * を使ってまとめて import することも可能です。

import java.util.*; // java.utilパッケージの全てのクラスをまとめてimport

public class MyClass {
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        ArrayList<String> list = new ArrayList<>();
    }
}

EclipseやIntelliJ IDEAなどのIDEを使っている場合は、import忘れを手で直す必要はありません。

エラー箇所にカーソルを合わせて、以下のショートカットキーを押せば import 文が自動で追加されます。

  • Eclipse: Ctrl + Shift + O
  • IntelliJ IDEA: Alt + Enter(macOSは Option + Enter)
  • Visual Studio Code: Quick Fix Ctrl + .

IntelliJ IDEAなら、次の設定を有効化しておくのがおすすめです。

Settings → Editor → General → Auto Import → Add unambiguous imports on the fly

import文の入力自体が不要になり、「シンボルを見つけられません」エラーの発生源を根元から断てます。

メソッドが見つからない(symbol: method)場合の解決方法

メソッドが見つからないエラーは、主に「スペルミス」や「引数の間違い」が原因で発生します。

原因1:メソッド名のスペルミス

最も単純で、最もよくある間違いです。

例えば、画面に文字を出力する println メソッドの l (エル) を I (アイ) と見間違えたり、スペルを少しだけ間違えたりするケースです。

悪い例:
public class Greeting {
    public static void main(String[] args) {
        System.out.printIn("Hello Java"); // ← "println" を "printIn" とタイポ
    }
}
良い例:

メソッド名を注意深く確認し、正しいスペルに修正します。printIn を println に直しましょう。

public class Greeting {
    public static void main(String[] args) {
        System.out.println("Hello Java"); // ← 正しいメソッド名に修正
    }
}

原因2:引数の型や個数が違う

メソッドを呼び出す際には、決められた型と個数の「引数」を渡します。

このルールが守られていない場合も、コンパイラは適切なメソッドを見つけられずにエラーを返します。ただし、メソッド名自体は存在して引数だけが合わない場合、javac は cannot find symbol ではなく no suitable method found for substring(no arguments)(候補が1つなら method ... cannot be applied to given types)というエラーを出します。この節の substring() の例もそのエラーです。

悪い例:
public class SubstringExample {
    public static void main(String[] args) {
        String text = "Java Programming";
        // 引数が1つも渡されていない(substring には int の引数が必要)
        String sub = text.substring(); // ← substringメソッドは引数が必要
        System.out.println(sub);
    }
}
良い例:

使用するメソッドの正しい使い方を調べ、必要な引数を正しく渡します。

substringメソッドは、切り出す開始位置や終了位置を数字で指定する必要があります。

public class SubstringExample {
    public static void main(String[] args) {
        String text = "Java Programming";
        // 例えば、5文字目から最後までを切り出す
        String sub = text.substring(5); // ← 開始位置の引数を追加
        System.out.println(sub);
    }
}

変数が見つからない(symbol: variable)場合の解決方法

変数のエラーは、「スペルミス」のほかに「宣言前の使用」や「スコープ外での使用」が主な原因です。

原因1:変数の宣言前に使用

プログラムでは、変数を使う前に「こういう名前で、こういう種類のデータを入れる箱を用意します」という「宣言」が必要です。

宣言より前の行で変数を使うと、コンパイラはその名前が何を指すのかわからずエラーになります。

悪い例:
public class VariableOrder {
    public static void main(String[] args) {
        System.out.println(count); // ← 変数 "count" を使うのが先になっている
        int count = 100; // ← 変数の宣言が後になっている
    }
}
良い例:

変数の宣言を、その変数を最初に使用する場所よりも前に移動させます。

public class VariableOrder {
    public static void main(String[] args) {
        int count = 100; // ← 先に変数を宣言する
        System.out.println(count); // ← その後に変数を使う
    }
}

原因2:スコープ外での使用

変数が有効な範囲を「スコープ」と呼びます。スコープは、通常、変数が宣言された波括弧 {} の内側です。

その範囲の外から変数を呼び出そうとすると、エラーが発生します。

悪い例:
public class ScopeExample {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            System.out.println("ループ内: " + i);
        }
        // ループの外側から変数 "i" を使おうとしている
        System.out.println("ループの外: " + i); // ← 変数 "i" は for文の中でしか使えない
    }
}
良い例:

その変数を使いたい場所で有効になるように、宣言する位置を調整します。

今回のケースでは、for文の外側で変数 i を使いたいのであれば、for文の外で宣言する必要があります。

public class ScopeExample {
    public static void main(String[] args) {
        int i = 0; // ← ループの外側で変数を宣言
        for (i = 0; i < 5; i++) {
            System.out.println("ループ内: " + i);
        }
        // ループが終わった時点の "i" の値(5)が表示される
        System.out.println("ループの外: " + i);
    }
}

実務では、変数のスコープは「必要最小限の範囲」に留めるのが鉄則です。スコープが広いと意図しない場所からの参照が増え、バグの温床になります。

「この変数はどこで宣言されている?」と迷ったときは、IntelliJ IDEAなら変数にカーソルを置いて Ctrl + B(macOS: Cmd + B)を押すと宣言元にジャンプできます。

あわせて読む

補足:privateメンバへのアクセスは別のエラーになる

原因:アクセス修飾子による制限

Javaでは、クラスのメソッドや変数に「アクセス修飾子」を付けることで、外部からのアクセスを制御できます。

privateが付いたメソッドや変数は、そのクラスの内側からしか使えません。

別のクラスから呼び出そうとすると、コンパイラは「private なのでアクセスできない」というエラーを返します。このエラーは cannot find symbol ではなく message has private access in MyClass という別の文言で出ます。

悪い例:
// MyClass.java
public class MyClass {
    private String message = "こんにちは"; // ← privateで宣言されている
}

// Main.java
public class Main {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        System.out.println(obj.message); // ← 別クラスからprivateの変数にアクセス
    }
}
エラーメッセージ:
Main.java:4: error: message has private access in MyClass
        System.out.println(obj.message);
                              ^
良い例:

private を public に変更するか、値を返す専用のメソッド(getter)を用意することで解決します。

一般的には、変数は private のまま、getter で値を取り出す方法が推奨されています。

// MyClass.java
public class MyClass {
    private String message = "こんにちは";
    // 外部からmessageを取得するためのgetterメソッド
    public String getMessage() {
        return message;
    }
}

// Main.java
public class Main {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        System.out.println(obj.getMessage()); // ← getterを通じてアクセス
    }
}

私の経験では、public フィールドを使っていたプロジェクトを引き継いだことがあります。

別チームのメンバーがフィールドを直接書き換えるコードを書いていました。

private + getter/setter に統一したところ、同種のバグが0件になりました。

アクセス修飾子は「面倒な制約」ではなく「事故を防ぐ安全装置」です。

あわせて読む

自作クラスが見つからない場合の解決方法(同一パッケージ)

複数ファイルに分けてプログラムを書いているとき、自作クラスが見つからないエラーが発生することがあります。

原因は、ファイル間の package 宣言が食い違っているケースがほとんどです。

悪い例:
// Animal.java
package jp.example; // ← パッケージ宣言あり
public class Animal {
    public void speak() { System.out.println("鳴く"); }
}

// Main.java
// package宣言なし(デフォルトパッケージ)
public class Main {
    public static void main(String[] args) {
        Animal a = new Animal(); // ← error: cannot find symbol
    }
}
良い例:

両方のファイルで package 宣言を揃えるか、import 文で明示的に読み込みます。

// Main.java
package jp.example; // ← Animalと同じパッケージを宣言

public class Main {
    public static void main(String[] args) {
        Animal a = new Animal(); // ← 同一パッケージなので import 不要
        a.speak();
    }
}

コマンドラインでコンパイルするときは、パッケージのルートディレクトリから javac jp/example/*.java のように実行するのがポイントです。

外部ライブラリ(Maven / Gradle)でシンボルが見つからない場合

外部ライブラリのクラスで cannot find symbol が出たら、原因は依存関係の追加漏れです。MavenやGradleのプロジェクトで特によく起きます。

Mavenの場合(pom.xml):
<!-- pom.xml に dependency を追加 -->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.14.0</version>
</dependency>
Gradleの場合(build.gradle):
// build.gradle に dependencies を追加
dependencies {
    implementation 'com.google.code.gson:gson:2.14.0'
}

追加後は必ずビルドツールを再実行(Maven: mvn install、Gradle: ./gradlew build)してください。

IDEを使っている場合は、「プロジェクトの更新 / Reload Project」で依存関係を再読み込みしてください。

Lombokで「cannot find symbol」が出る場合(@Builder/@Slf4j)

Lombok(@Builder、@Slf4j、@Getter/@Setter 等)を使ったプロジェクトの cannot find symbol は、アノテーションプロセッサの設定不足が原因です。

Lombokはコンパイル時にアノテーションプロセッサでコードを自動生成するため、この設定が無いとコンパイラが生成コードを見つけられません。

IntelliJ IDEAの場合:

Settings → Build, Execution, Deployment → Compiler → Annotation Processors で「Enable annotation processing」にチェックを入れてください。

Annotation Processing が無効だと、Lombokが生成する builder() や log 変数が見つからずエラーになります。

Mavenの場合:
<!-- pom.xml の maven-compiler-plugin に annotationProcessorPaths を追加 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <annotationProcessorPaths>
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.46</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</plugin>
Gradleの場合:
// build.gradle に compileOnly と annotationProcessor の両方を追加
dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.46'
    annotationProcessor 'org.projectlombok:lombok:1.18.46'
}

Lombokのバージョンが古いと Java 21以降 で cannot find symbol が発生します。

Java 21は1.18.30以降、Java 25は1.18.40以降が対応しています。それより古い場合はLombokを更新してください。

あわせて読む

補足:static の呼び出しミスは別のエラーになる

static メンバの呼び出し方を間違えても、多くの場合 cannot find symbol にはなりません。インスタンス経由で static メソッドを呼ぶのはコンパイルが通り(警告のみ)、インスタンスメソッドをクラス名で呼ぶと non-static method ... cannot be referenced from a static context という別のエラーになります。cannot find symbol になるのは、MathHelper.nothing() のようにその名前の static メンバ自体が存在しないときです。

悪い例:
// MathHelper.java
public class MathHelper {
    public static int square(int n) { return n * n; }
}

// Main.java
public class Main {
    public static void main(String[] args) {
        MathHelper helper = new MathHelper();
        // staticメソッドをインスタンス経由で呼んでいる(コンパイルは通る。javac -Xlint:static では警告)
        int result = helper.square(5);

        // 逆に、インスタンスメソッドをクラス名で呼ぼうとする
        // String.length(); ← error: non-static method length() cannot be referenced from a static context(インスタンスメソッドをクラス名で呼んだ場合)
    }
}
良い例:

static メソッドは クラス名.メソッド名() の形で呼び出します。インスタンスを作る必要はありません。

public class Main {
    public static void main(String[] args) {
        int result = MathHelper.square(5); // ← クラス名で直接呼び出す
        System.out.println(result); // 25
    }
}

原因番外:new キーワードを書き忘れている場合

インスタンス生成で new を書き忘れたケースです。

コンパイラは「クラス名と同じ名前のメソッドを呼び出そうとした」と解釈し、cannot find symbol を返します。

悪い例:
public class Main {
    public static void main(String[] args) {
        MyClass obj = MyClass(); // ← new を書き忘れている
    }
}
良い例:
public class Main {
    public static void main(String[] args) {
        MyClass obj = new MyClass(); // ← new を付ける
    }
}

IDEを使っていれば入力した瞬間に赤線で検知されます。テキストエディタで書いている場合は、このパターンをつい見落としがちなので注意しましょう。

Javaバージョン不一致でcannot find symbolが出る場合

使用しているJavaバージョンに存在しないAPIを呼び出すと cannot find symbol が発生します。

代表例は、Java 21で追加された List.getFirst() / List.getLast() です。Java 14で追加された @Serial アノテーションも該当します。

よくあるパターン:
  • List.getFirst() / List.getLast() → Java 21以降で追加。Java 17以下では list.get(0) / list.get(list.size() - 1) を使う
  • javax.annotation.Generated → Java 9で非推奨化されデフォルトで読み込まれなくなり、Java 11で完全に削除。import javax.annotation.Generated; の行では package javax.annotation does not exist が出て、@Generated の使用箇所で cannot find symbol が出ます。jakarta.annotation.Generated に変更するか、javax.annotation-api を依存関係に追加する
  • javax.annotation.PostConstruct → 同様にJakarta EE 9以降は jakarta.annotation.PostConstruct に移行

確認方法: pom.xml / build.gradle のソースバージョン設定を確認します。あわせて、IDEの Project Structure → Language Level と一致しているかも見てください。

チーム開発では、メンバー間でJavaバージョンが異なると「自分の環境では動くのに他の人はエラー」という状況が起こります。

あわせて読む

コードは正しいのに直らないときの切り分けフロー

スペル・import・スコープを見直しても消えない場合は、コードではなくビルド環境側を疑います。エラーが「どこで出るか」から切り分けると、確認する設定を1つに絞れます。

コードは正しいのに消えないときの切り分け(どこで出るか)
エラーはどこで出る?
IDEの赤線だけIDEのキャッシュ・SDK設定Invalidate Caches / プロジェクト再読み込み
javacコマンドクラスパス(-cp)とパッケージのフォルダ構成を確認
mvn / gradle のビルド次の図の順に確認外部ライブラリ → Lombok → Javaバージョン
mvn / gradle のビルドで出るときの確認順(Q1から順に答える)
QUESTION / 質問
はい
いいえ
Q1. 外部ライブラリのクラス?
pom.xml / build.gradle に依存関係を追加して clean build
Q2へ
Q2. Lombokが生成するメソッド?builder() / log など
アノテーションプロセッサを有効化
Q3へ
Q3. 新しいAPIや var を使っている?
ソース / IDEのJavaバージョンを揃える
javax → jakarta などパッケージ名の移行を確認

エラーを再発させないためのチェックリスト

エラーは「出てから直す」より「出さない書き方」を身につけるほうが、結果的に開発が速く進みます。

cannot find symbolエラーの原因は、おおよそ次の順でよく見かけます(統計ではなく目安です)。

順位原因
1位import忘れ
2位スペルミス
3位スコープ外参照
4位依存関係不足
5位その他

とくに多いのはimport忘れとスペルミスなので、まずこの2つを疑うのが最短ルートです。

スペル・大文字小文字を確認する

今回紹介したエラー原因の多くは、単純なスペルミスでした。Javaは大文字と小文字を厳密に区別する言語であることを常に意識しましょう。

ポイント

  • String と string は別物
  • System と system は別物
  • main と Main は別物

コードを書くときは、一文字一文字を丁寧に確認する癖をつけるのがおすすめです。

パスやクラスパスを正しく設定する

クラスパスの設定は、コマンドプロンプトやターミナルで javac / java コマンドを直接打ってコンパイル・実行する場合に特に重要です。

javac / java コマンドで java.lang.NoClassDefFoundError のようなエラーが出たら、クラスパスの設定ミスを疑ってください。

クラスパスとは、Javaがコンパイルされた .class ファイルを探しに行く場所のリストです。

基本的には、コンパイルしたい .java ファイルがあるディレクトリで、以下のように実行すれば問題ありません。

// カレントディレクトリ(今いる場所)をクラスパスに指定してコンパイル
javac -cp . MyProgram.java

// カレントディレクトリをクラスパスに指定して実行
java -cp . MyProgram

-cp . は「カレントディレクトリをクラスパスに含める」という意味で、多くの場合この指定で解決します。

javac で直接コンパイルするときは、依存する他のクラスの扱いにも注意してください。参照先のソースが見つからない配置だと cannot find symbol になります。

javac Foo.java Bar.java のように関連ファイルをまとめて指定すると確実です。

あわせて読む

IDEの補完機能を活用する

開発現場では、EclipseやIntelliJ IDEA、Visual Studio Codeといった統合開発環境(IDE)を使うのが一般的です。

IDEは、単なるテキストエディタではありません。

ポイント

  • コード補完機能: Sy と打っただけで System の候補を出してくれる
  • エラーのリアルタイム検知: コードを書いているそばから、間違っている箇所に赤線などを引いて教えてくれる
  • 自動インポート: import文を自動で追加してくれる

IDEの補完・検知・自動インポート機能を活用すれば、「シンボルを見つけられません」のような初歩的なエラーの多くは発生した瞬間に気づいて修正できます。

学習効率も劇的に向上します。まだテキストエディタだけでプログラミングをしているなら、IDEの導入を検討してみてください。

「シンボルを見つけられません」エラーのよくある質問

Q1. コンパイルは通るのに実行時に cannot find symbol が出るのはなぜ?

A1. cannot find symbol はコンパイルエラーです。コンパイルが通った後の実行時には出ません。

実行時に似たメッセージが出る場合は、java.lang.NoClassDefFoundError や ClassNotFoundException の可能性が高いです。クラスパス(-cp)の設定不足や、JARファイルの配置漏れを確認してください。

あわせて読む

Q2. IDE上では赤線が出ないのにビルドで cannot find symbol が出る

A2. Maven / Gradle の依存キャッシュが破損している可能性があります。以下のコマンドでクリーン&再ビルドしてください。

# Maven
mvn clean install

# Gradle
./gradlew clean build --refresh-dependencies

それでも解消しない場合は、IDEの「プロジェクト再読み込み / Invalidate Caches」を試してください。

Q3. var を使ったら cannot find symbol が出る

A3. var キーワードは Java 10 以降で使えます。

Java 8 / 9 で書いたり、IDEの language level が 9 以下に設定されていると cannot find symbol になります。

pom.xml / build.gradle のコンパイラバージョンと、IDEのプロジェクト設定を Java 11 以上に揃えてください。

Q4. javacコマンドで直接コンパイルするとcannot find symbolが出るのはなぜ?

A4. 参照先のクラスをコンパイラが見つけられないことが原因です。Foo.java と Bar.java が同じフォルダにあって package 宣言がなければ、javac Foo.java だけでも Bar.java が自動的に探されてコンパイルされます。エラーになるのは、package 宣言とフォルダ構成がずれていて、javac が Bar.java を探せないときです。

その場合は javac Foo.java Bar.java のように関連ファイルをまとめて指定するか、パッケージのルートディレクトリから javac jp/example/*.java のように一括コンパイルしてください。

Q5. Lombokでcannot find symbolが出たらまず何を確認すればいい?

A5. まずアノテーションプロセッサが有効かを確認してください。

IntelliJ IDEAなら「Settings → Build, Execution, Deployment → Compiler → Annotation Processors」で「Enable annotation processing」にチェックが入っているかを見ます。Maven/Gradleなら、Lombokがannotation processorの依存関係として設定されているかを見直します。

Q6. import java.util.*;のようにアスタリスクでまとめてimportしても問題ない?

A6. 問題ありません。同じパッケージに属する複数のクラスを使う場合、アスタリスク*を使えばまとめてimportできます。ただし可読性の観点から、実務では使用するクラスを個別にimportするスタイルが推奨されることが多いです。

Q7. package宣言が原因のcannot find symbolはどう直せばいい?

A7. 参照する側とされる側のファイルで、package宣言を揃えるか、import文で明示的に読み込みます。パッケージ宣言のあるクラスからは、デフォルトパッケージ(package宣言なし)のクラスを import できません。逆に、デフォルトパッケージのクラスから、パッケージ宣言のあるクラスを import jp.example.Animal; で参照することはできます。

まとめ:cannot find symbolエラーの原因7つを振り返り

このエラーは、コンパイラが指定された名前(シンボル)を見つけられないときに発生します。

エラーに遭遇したら、まずは慌てずにエラーメッセージをよく読み、どのファイルの何行目で、どのシンボルが見つからないのかを特定しましょう。

原因は以下の7つのパターンに絞られます。エラーが解決しないときはこのリストを上から順にチェックしてみてください。

ポイント

  1. スペルミスや大文字・小文字の間違い
  2. import文の不足
  3. 変数の宣言忘れやスコープ外での使用
  4. newキーワードの書き忘れ(MyClass obj = MyClass();)
  5. 自作クラス・同一パッケージでの package 宣言の食い違い
  6. 外部ライブラリ(JAR / Maven / Gradle)の依存関係が追加されていない
  7. ビルド環境の不一致(Lombok のアノテーションプロセッサ未設定・Java バージョンの不一致)

エラーメッセージの symbol: 行(class / method / variable)を確認し、上のリストを1つずつ当たってください。それで解決の糸口が必ず見つかります。

REVISIONS / 改訂履歴
REV.DATE内容
52026-10-15図解を描き直し(図面のデザインにそろえた)
42026-10-14雰囲気だけの挿絵を外した
32026-08-202026年8月時点の情報で全体を見直し(古い記述を2件更新)
22026-07-122026年7月時点の情報で全体を見直し(古い記述を4件更新)
12025-09-14初版
NEXT READ本棚から1本

AIで開発を組み直すなら、まずこの5冊から

入門・実践・設計まで、Claude Codeの本をレベル別に5冊選んで比べました。

→ おすすめ5冊を見る

  • この記事を書いた人
  • 最新記事

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

Java入門 ・