web-dev-qa-db-ja.com

パッケージ名はフォルダ構造とは異なりますが、それでもJavaコードはコンパイルされます

Notepad ++を使用してJavaコードを記述し、コマンドプロンプトを使用してコンパイルして実行しています。以下は私のサンプルJavaコード、

    package abraKadabra;

    public class SuperClass{
       protected int anInstance;

       public static void main(String [] abc){
           System.out.println("Hello");
       }
    }

ただし、このファイルは次のフォルダ構造にあります。

"usingprotected\superPkg"(usingProtectedは、Cの階層のどこかにあるフォルダーです:)

したがって、ここでの私のパッケージ名は、私が書いたabraKadabraの代わりにusingProtected.superPkgのようなものにする必要があります。

しかし、このJavaコマンドプロンプトからのコードをコンパイルすると、エラーや警告なしで正常にコンパイルされます。なぜそうなのですか?パッケージ名はフォルダー構造に準拠するべきではありませんか?どのように付着する必要がありますか?

例:パッケージ名がusingProtected.superPkgの場合、コンパイラは逆の順序でチェックします。現在の作業ディレクトリはsuperPkgである必要があり、次に親ディレクトリはusingProtectedである必要があります。パッケージ名でフォルダ構造をチェックする方法ですか?

24
whitehat

少し実験した後、パッケージ名を使用して、コマンドプロンプトからJavaクラスファイルを実行する方法を学びました。

以下が私のJavaソースファイルであると仮定します:-

    package mySample;


    public abstract class Sample{
        public static void main(String... a){
           System.out.println("Hello ambiguity");
        }
    }

このファイルは、ディレクトリ「D:\ Code NCode\CommandLine」にあります。

ここで、次のコマンドを使用してソースコードをコンパイルするとき(cmdから上記のディレクトリに移動することにより):-

    javac -d . Sample.Java

これにより、現在のディレクトリに「mySample」フォルダが自動的に作成されます。したがって、私のクラスファイルSample.classは、ディレクトリ「D:\ Code NCode\CommandLine\mySample」にあります。コンパイラは、ソースコードで指定したパッケージ名からこの新しいフォルダ「mySample」を作成しました。

したがって、パッケージ名を「package com.mySample」に指定した場合、コンパイラは2つのディレクトリを作成し、クラスファイルを「D:\ CodeNCode\CommandLine\com\mySample」に配置します。

現在、私はまだ現在の作業ディレクトリ、つまり「D:\ Code NCode\CommandLine」にいます。そして、クラスファイルを実行するために、次のコマンドを実行します。

    Java mySample.Sample

そこで、パッケージの完全な階層を示し、次にクラス名を示します。 Javaインタプリタは、現在のディレクトリで「mySample」ディレクトリを検索し、その中で「Sample.class」を検索します。正しく取得され、正常に実行されます。:)

さて、なぜ間違ったパッケージソースコードをコンパイルするのかと尋ねると、コードは正常にコンパイルされますが、クラスファイルを実行するとNoClassDefFoundErrorが発生します。したがって、上記の方法を使用して、コマンドラインからパッケージ名を使用できます。

7
whitehat

Java言語仕様では、ファイルを特定のディレクトリに強制することはありません。オプションでコンパイラが要求できるようになりますパブリッククラスはクラスと同じ名前のファイルにありますが、パッケージに似たものはないと思います。 セクション7.2.1 ファイルシステムで可能なストレージオプションについて説明していますが、そうではありません。私が見る限り、ソースコード構造の強制については何も言わないでください。

ただし、ソースディレクトリ構造にパッケージ構造を反映することはベストプラクティスであり、ほぼ一般的に受け入れられている規則です...そしてjavacwillはこれを使用しますコンパイルするように明示的に指定されていないソースファイルを見つけようとします。

コマンドラインからコンパイルする場合、デフォルトでは、各クラスは対応するソースファイルと同じ場所に表示されますが、「-d」オプション(「-dbin」など)を使用すると、コンパイラがビルドすることに注意してください。指定されたディレクトリをルートとする、適切な出力ディレクトリ構造。

48
Jon Skeet

単一のクラスをコンパイルする場合、javacは他の場所でそのクラスを探す必要はありません。ファイルをそのままコンパイルし、結果の.classを同じフォルダーに配置します。ただし、通常、クラスパスのいずれかのディレクトリにある「abraKadabra」ディレクトリに配置するまで、クラスを使用することはできません。

ただし、クラスがパッケージ内の別のクラスを使用している場合は、同じ理由で、そのクラスをコンパイルする際に問題が発生する可能性があります(javacはクラスを見つけて、クラスにメソッドなどがあることを確認したい使用)。

4
cHao

Javaコンパイラは、ソースファイルをコンパイルするときにディレクトリ構造をチェックしません。あなたが言ったように、ディレクティブで始まるソースファイルがあるとしましょう

package abraKadabra;

サブディレクトリ.../abraKadabraに含まれていない場合でも、ファイルをコンパイルできます。ソースファイルは、他のパッケージに依存しない場合、エラーなしでコンパイルされます。ただし、結果のプログラムは実行されません(実行時にパッケージ名も含まれていない場合)。プログラムを実行しようとしても、仮想マシンは結果のクラスを見つけられません。

0
MMKarami