発想が逆だと思います。
まず、あるソースをコンパイルするときに依存するclassファイルがすでにあるとは限りません。
Java
1package p0;
2
3public class A {
4 public void hoge(p1.B b) {
5 b.fuga();
6 }
7 public void fuga() {
8 System.out.println("A fuga!");
9 }
10}
Java
1package p1;
2
3public class B {
4 public void hoge(p0.A a) {
5 a.fuga();
6 }
7 public void fuga() {
8 System.out.println("B fuga!");
9 }
10}
こんな風な関係の、p0.A
とp1.B
があったとします。果たしてこの二つはどちらからコンパイルすれば良いのでしょうか?p0.A
をコンパイルするにはp1.B
の情報が必要です。逆にp1.B
をコンパイルするにはp0.A
の情報が必要です。でも、実際にこれらはコンパイル可能です。なぜなら、classファイルだけではなく、ソースファイルもjavacは見に行くからです。
p0.A
をコンパイルしようとするとき、コンパイラはp0.A
の枠組みの情報(どんなクラスでどんなメソッドがあるか)を読み込みます。実際の内部をコンパイルするにはp1.B
が必要となったので、p1.B
を探しに行きます。しかし、まだコンパイルされていないのでclassファイルはありません。そこで、今度はp1.B
のソースファイルを探しに行きます。p1.B
のソースファイルを見つけると、同じようにp1.B
の枠組みの情報(どんなクラスでどんなメソッドがあるか)を読み込みます。これで、p0.A
を実際にコンパイルすることが可能になると言うことです。(実際は、p1.B
もコンパイルされるようですので、先にp0.A
の読込済み情報を使ってp1.B
をコンパイルしているのかも知れません。)
つまり、ソースファイルもclassファイルと同様に、パッケージ名とクラス名から、どこに存在するのかがわからなければなりません。Javaはその探索方法をディレクトリ名とファイル名に制限をかけることで自動で探しに行けるようにしたのです。
では、package宣言をなくしても良いのではとなりますが、今度はどうやってどのパッケージなのかが判断すれば良いのかがわかりません。javacでコンパイルするソースファイルを指定するときに、パッケージを想定した相対パスであるとは限らないからです。絶対パスでわたされたらどうなるでしょうか?javac -sourcepath .. A.java
みたいなのはどう判別すれば良いのでしょうか?もし、どのパッケージにあるファイルかがソースファイルに存在しなければ、コンパイルでのファイル名指定に大きな制約が必要になってきます。コンパイルの仕方を間違えると意図しないパッケージに入ることになってしまいます。
実際のjavacの動きとして、ファイルを単体でコンパイルする場合はパッケージ名のディレクトリに置いておく必要はありません。パッケージ名のディレクトリに置くのは、classファイルがないときにソースファイルを見つけるためだけに過ぎないのです。どのパッケージのclassファイルになるかはソースコードに書いてある通りになると言うことです。
何を言いたいかというと、経緯が逆ということです。名前空間を分ける必要性から、パッケージのような概念は必須でした。そこでpackageが作られたと思われます。そして、JavaがC++等とは違って画期的だったのが、パッケージ名とクラス名から、必要になるソースファイルやclassファイルを自動的に探索できるようにしたということです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/05/25 11:06