いまさら聞けないjavaのpackageとimport

javaを始めるとすぐ出てくるのがpackageとimportです。

まず一番初めにpackageとfileのパスは関係がないということです。

このpackageの階層が関係してくるのはjavacでコンパイルした後のclass fileのパスです。ここがなかなか気づけませんでした。

例えばpackage com.sample の下にclass MyClassを定義したとします。

package com.sample;
class MyClass{
  public static void main(String[] args){
    System.out.println("hello”);
  }
}

これをjavacでコンパイルして出来たMyClass.classを実行するためにはこのMyClass.classがcom/sampleの下にあってcomフォルダがある位置から

java com.sample.MyClass

と実行しなければなりません。

逆に言えば.MyClass.javaファイルはどこにいても構いません。src/MyClass.java でも com/sample/MyClass.javaでもokです。

コンパイルした時にファイルの階層を作るのは面倒なので javac の -d オプションを使います。-d ./class とやれば実行しているカレントディレクトリのclassフォルダの中に自動的にcom/sampleとフォルダを作ってそこにMyClass.classファイルを入れてくれます。

.
├── MyClass.java
└── class

こういう状態でjavac -d ./class MyClass.java してみましょう。

.
├── MyClass.java
└── class
    └── com
        └── sample
            └── MyClass.class

com/sampleとフォルダが出来ています。

次にimportです。importはclassファイルのパスを指定して使うことができるようにするためのコマンドです。

そしてこれもclassファイルのパスでありjavaファイルのパスではありません。

例えばcom.sampleの下にlibを作ってその中にAnotherClassを入れてみましょう。

package com.sample.lib;
public class AnotherClass{
  public void hello(){
    System.out.println("hello another class");
  }
}

こんな感じです。

javac MyClass.java AnotherClass.java -d class

コンパイルすると

.
├── AnotherClass.java
├── MyClass.java
└── class
    └── com
        └── sample
            ├── MyClass.class
            └── lib
                └── AnotherClass.class

こうなります。MyClassからAnotherClassをimportしてみましょう。

package com.sample;
import com.sample.lib.AnotherClass;

class MyClass{
  public static void main(String[] args){
    AnotherClass another = new AnotherClass();
    System.out.println("hello");
    another.hello();
  } 
} 
javac MyClass.java AnotherClass.java -d class

コンパイルして

cd class
java com.sample.MyClass

classフォルダに移動して実行すると

hello hello another class

無事にimportできました。