- ベストアンサー
package宣言のディレクトリ構造
はじめまして、Java初心者な質問です。 package宣言するときの、ディレクトリの構造がどうあるべきか?という質問なのですが、 例えばカレントディレクトリが /home/test/java にあるとして ----------// ClassA.java //----------- package a.b; public class ClassA { /** コンストラクタ */ public ClassA() { } } とした場合、 ClassA.javaファイルとClassA.classはどこに保存されるべきなのでしょうか? 参考書などによると 「aディレクトリ内のbディレクトリ」と書いてあるのですが、どこから見てのaディレクトリ内のbディレクトリなのでしょうか? この場合だと、/home/test/java/a/b/ClassA.java という事なのでしょうか、、? それだったらpackage宣言が package home.test.java.a.b; になるような気がして、困惑しています。 よろしくお願いします><
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
> 「aディレクトリ内のbディレクトリ」と書いてあるのですが、どこから見てのaディレクトリ内のbディレクトリなのでしょうか? classpathから見て、です。 chasspathが /home/test/java に設定されていれば、package a.b が参照するディレクトリは /home/test/java/a/b となりますし、classpathが /foo/bar なら、参照ディレクトリは /foo/bar/a/b となります。 > No.2のお礼の件 原因はおそらく /home/test/java/ClassA.java です。 少々難しい話になりますが、理解してください。 import a.b.* とした場合、ClassB.java中のソースに登場するクラス ClassAはパッケージ名なしのClassAか、a.b.ClassAか、その時点では判別できません。 よって、まずパッケージ名なしのClassAを探します。 パッケージ名なしのClassAはクラスパス直下にある(今回の場合はカレントディレクトリ=/home/test/java)ので、コンパイラはまず /home/test/java/ClassA.class または/home/test/java/ClassA.javaを探します。 ここでコンパイラは /home/test/java/ClassA.java を発見するので、ClassB.java中のClassAはパッケージ名なしのClassAと決定します。 ところが、このClassA.javaにかかれているクラスの内容はa.b.ClassAのソースで、パッケージ名なしのClassAではありません。 よって、/home/test/java/ClassA.java には「パッケージ名なしのClassAに関する情報が含まれていません」というエラーを返します。それがNo.2お礼で出てくるエラーメッセージです。 ご理解いただけたでしょうか。 要は /home/test/java/ClassA.java を除去するか、ClassA.javaを/home/test/java/a/b に移動させればコンパイルできます。 が、除去か移動をしなければならない理由は上記によるものです。
その他の回答 (2)
- kamkamkam3
- ベストアンサー率42% (216/514)
基準のディレクトリはすきなところにできます。 c:\test\javaを基準フォルダにすると javaフォルダの中のソースはjavac ***.javaでコンパイルできます。 このフォルダを基準フォルダにすると package a.b;で宣言されたファイルは 基準フォルダから考えて 基準フォルダ\a\b というフォルダに入れなくてはいけません。フォルダは広くディレクトリとも言われます。 要するに基準フォルダからパッケージ階層を作れるのがJava言語の規則なのです。いつでもどこでも絶対パス(作者の場合です/home/test/java/a/b/)にパッケージ階層を指定すると、ひどい弊害があります。UNIXシステムは基本的に一般ユーザーは特定のフォルダしか使えません。ですから、パッケージ階層は自分の使いたくないフォルダ名まで含めないといけなくなります。また、一般的にパッケージ階層の名前というのは慣例があります。企業の名前とか。そういった純粋なパッケージ名にするためにも自分の好きな基準フォルダを決めてそこからパッケージを作れる事になっています。そうすることにより、自分の好きなパッケージ名を作れる事となります。 早い話が元からの全部のフォルダ名をパッケージ名につけるより、自分の好きなフォルダからパッケージ名をつけた方が好きな名前がつけられるというだけです。
お礼
回答ありがとうございます。 Java勉強はじめたばかりで、とても参考になりました。 自分の環境(Linux CentOS / JDK1.5)でいろいろ試してて、パッケージ宣言をしたクラスを別クラスからnew()しようとして、コンパイルエラーが出てつまづいていました^^; 下のお礼にも書いたのですが、別クラス(ClassB.java)で import a.b.ClassA; とすればコンパイルが通るのですが、 import a.b.*; とするとコンパイルできません>< ------// コマンド //-------- $ javac -classpath . ClassB.java ---------// エラーメッセージ //--------- ClassB.java:5: cannot access ClassA bad class file: ./ClassA.java file does not contain class ClassA Please remove or make sure it appears in the correct subdirectory of the classpath. ディレクトリ構造は /home/test/java/ClassB.java /home/test/java/a/b/ClassA.class です、、。 ClassB.javaのソースは下のお礼に書いたとおりです。 また時間があるときにアドバイス頂けたら幸いです。
>この場合だと、/home/test/java/a/b/ClassA.java という事なのでしょうか、? もし、/home/test/java/内にプログラムを作成しているなら、そうです。 あくまで「どこに作成しているか」からみた相対位置ですので。 >「aディレクトリ内のbディレクトリ」と書いてあるのですが、どこから見てのaディレクトリ内のbディレクトリなのでしょうか? プログラムを実行する際の起動ディレクトリからみた相対位置です。プログラムを実行するとき、/home/test/java/にカレントディレクトリを移動して実行をしますね? すると、そのディレクトリ内にある「a」がaパッケージに、その中の「b」がa.bパッケージになるわけです。
お礼
回答ありがとうございます! なるほどでした。 ということは /home/test/java に ClassA.java(このファイルはどこでも良いのでしょうが、、) を /home/test/java/a/b に ClassA.class を ということですね。 > プログラムを実行する際の起動ディレクトリからみた相対位置です。 ということは、 /home/test/java/ClassB.java => コンパイル => /home/test/java/ClassB.classを作成 ----------// ClassB.java // ---------- import a.b.ClassA; public class ClassB { /** コンストラクタ */ public ClassB() { ClassA classA = new ClassA(); } } という事ですね! というかそうしたらできました^^;
お礼
とてもよく分かりました! てっきりコンパイル時にコンパイラは X.class ファイル(クラスファイル)のみを探すものだと、決め付けてました、、。 テストで作成したClassA.javaを移動させたら、bgbgさんのおっしゃるとおりコンパイルが通りました。 kamkamkam3さん、kyon2_PaPaさん、bgbgさん、本当にありがとうございました!!><