パッケージ①
パッケージとインポート宣言
データとメソッドを集めて包んだものがクラスでありますが、クラスを集めて包んだものがパッケージになります。
パッケージ
あるプログラマが作ったクラスと別のプログラマが作ったクラスの名前が同じで1つのプログラムで使うとどうなるでしょうか?しかし、エラーの心配等はいりません。パッケージ(package)という論理的な名前空間で、名前の通用する範囲を自由に制御できるからです。パッケージのイメージを具体的にすると以下の図のようになります。
パッケージ p に所属するクラス Type は、p.Type と表記します。そのため、図の2つのクラスは、それぞれorigin.rectangleInfoとanother.rectangleInfo となります。このようにして、名前の衝突回避・使い分けをします。このとき、origin.rectangleInfo のような型のフルネームを完全限定名(fully qualified name)と呼び、単なるクラス名 rectangleInfo を単純名(simple name)と呼びます。また、パッケージは階層化でき、パソコンのディレクトリによく似ています。
パッケージの主な役割は以下の3つです。
- 名前の衝突回避
- カテゴリによる分類
- カプセル化(アクセス制御)
型インポート宣言
型のフルネームを表す完全限定名は、綴りが長くなります。パッケージ名を省略した単純名だけで型を利用可能にするのが、型インポート宣言(type import declaration)です。
単一型インポート宣言
以下の形式で単一の型をインポートします。
import 完全限定名;
この形式でインポートされた型名は、そのソースプログラム内で単純名だけで利用できます。この形式の宣言を行うプログラムが以下になります。
//Circle3.java
//円の面積を求める
import java.util.Scanner;
public class Circle3 {
public static void main(String[] args){
Scanner stdIn = new Scanner(System.in);
System.out.println("円の面積を求めます。");
System.out.print("半径:");
double r = stdIn.nextDouble();
System.out.println("面積は" + (Math.PI * r * r) + "です。");
stdIn.close();
}
}
java.util.Scanner のインポート宣言しているので、ソースプログラムでは、 Scanner を単純名だけで表せます。インポート宣言がなければ、以下のように完全限定名を使う必要があります。
java.util.Scanner stdIn = new java.util.Scanner(System.in);
オンデマンド型インポート宣言
ソースファイル中で利用する全クラスに対して単一型インポート宣言を行う作業は大変になります。そのため、以下の簡易的なインポート方法があります。
import パッケージ名.*;
この宣言を行ったプログラムでは、パッケージ名で指定されたパッケージに所属する型名を、単純名だけで利用できます。
//NumGussing.java
//数当てゲーム(0-99)
import java.util.*;
public class NumGussing {
public static void main(String[] args){
Random rand = new Random();
Scanner stdIn = new Scanner(System.in);
int num = rand.nextInt(100);
System.out.println("数当てゲームスタート");
System.out.println("0~99の値を当ててください。");
int x;
do{
System.out.println("数を入力してください。:");
x = stdIn.nextInt();
if(x > num)
System.out.println("もっと小さい数です。");
else if(x < num)
System.out.println("もっと大きい数です。");
}while(x != num);
System.out.println("正解です。");
stdIn.close();
}
}
java.lang パッケージの自動インポート
java.lang パッケージには、Java言語に密接に関連したクラスが集められています。そのため、このパッケージ内で宣言されている型名は、自動的にインポートされることになっています。Javaのソースプログラムでは、あたかも次に宣言するかのように扱われます。
import java.lang.*; //すべてのJavaプログラムで行われる暗黙の宣言
java.langパッケージに含まれる主な型名の一覧を以下の表に記しておきます。
インタフェース | Appendable CharSequence Cloneable Compareable<T> Iterable<T> Readable Runable Thread. UncaughtExceptionHandler |
クラス | Boolean Byte Character Character.Subset Character.UnicodeBlock Class<T> ClassLoader Compiler Double Enum<E extends Enum<E>> Float InheritableThreadLocal<T> Integer Long Math Number Object Package Process ProcessBuilder Runtime RuntimePermission SecurityManager Short StackTraceElement StrictMath String StringBuffer StringBuilder SystemThread ThreadGroup ThreadLocal<T> Throwable Void |
アナテイション | Deprecated OverRide SuppressWarnings |
静的インポート宣言
クラスの型だけでなく、静的なメンバである以下の2つもインポートできます。
- クラス変数(静的フィールド)
- クラスメソッド(静的メソッド)
これらのインポートを行うのが、静的インポート(static import)と呼ばれるインポートです。型インポート宣言と同様に、静的インポートの宣言にも2種類があります。
import static 型名.識別名; //単一静的インポート宣言
import static 型名.*; //オンデマンド静的インポート宣言
静的インポートを利用したプログラム例を以下に示します。
//Circle4.java
//円の面積を求める(円周率Math.PIを静的インポート)
import java.util.Scanner;
import static java.lang.Math.PI;
public class Circle4 {
public static void main(String[] args){
Scanner stdIn = new Scanner(System.in);
System.out.println("円の面積を求めます。");
System.out.print("半径:");
double r = stdIn.nextDouble();
System.out.println("面積は" + (PI * r * r) + "です。");
stdIn.close();
}
}
このプログラムでは、java.lang.Math クラスに所属する変数PIを静的インポートした上で、単純名としてアクセスしています。
画面への表示とキーボードからの読み込みで利用するSystem.outとSystem.inは、Systemクラスに所属します。これらを静的インポートした場合のプログラムを以下に示します。
//Circle5.java
//円の面積を求める(System.inとSystem.outを静的インポート)
import java.util.Scanner;
import static java.lang.Math.PI;
import static java.lang.System.in;
import static java.lang.System.out;
public class Circle5 {
public static void main(String[] args){
Scanner stdIn = new Scanner(in);
out.println("円の面積を求めます。");
out.print("半径:");
double r = stdIn.nextDouble();
out.println("面積は" + (PI * r * r) + "です。");
stdIn.close();
}
}