| 2010/08/08 | パッケージ | Javaの基本 |
| 2010/07/25 | クラスメソッド | Javaの基本 |
| 2010/07/20 | クラス変数 | Javaの基本 |
| 2010/07/07 | インターフェース (3) 多重継承 | Javaの基本 |
| 2010/07/04 | インターフェース (2) 定数 | Javaの基本 |
| 2010/07/01 | インターフェース (1) 基本 | Javaの基本 |
| 2010/06/25 | 抽象クラス | Javaの基本 |
| 2010/06/18 | オーバーロードとオーバーライド | Javaの基本 |
| 2010/06/14 | オーバーライド | Javaの基本 |
| 2010/06/10 | スーパークラスのコンストラクタ | Javaの基本 |
|
|
パッケージ
今回はパッケージについてみていきます。
パッケージとは
※wikipedia引用
Javaパッケージは名前空間の中にあるJavaクラスをまとめるメカニズムである。 Javaパッケージは、JARファイルと呼ばれる圧縮ファイルの中に保存することができ、クラス群を一つのグループとしてまとめた方が1つずつダウンロードするよりも高速化される。プログラマも一般に同じカテゴリに属しているクラスや類似した機能を提供するクラスをまとめたパッケージを使う。
階層構造を持たず、クラス名の衝突を避けるために存在する。またそのパッケージ内にあるクラスに対しては、package privateといった設定が可能であり、package privateなクラスはパッケージ外部のクラスからのアクセスが禁止され、カプセル化による情報隠蔽を実現できる。
Javaを開発しているとクラスやインターフェースを再利用したいときがあります。そのとき、例えばAさんが作ったクラスとBさんが作ったクラスを再利用したいのですが、クラス名が重なってしまいました。重複のたびにクラス名を修正していくのは結構手間です。そこでAさんが作ったクラスは「makeA」というパッケージに入れ、Bさんが作ったクラスは「makeB」のパッケージに入れておくと、クラスの重複が起こったときにどのパッケージのクラスを利用すると指定することができます。
外部に公開するときはなおさらクラス名の重複が起こりやすいです。外部公開のときは「ドメイン名を逆から書いたものをパッケージ名にする」などの暗黙の規則があるようですが、パッケージの目的の1つに「クラス名の衝突を避ける」ということがあります。
他にも同じカテゴリや類似した機能をパッケージとしてまとめることによりクラスやインターフェースを使いやすくなります。
パッケージの宣言
【makeA > PackageSample.java】
package makeA;
public class PackageSample {
public void show(){
System.out.println("makeAパッケージです。");
}
}
【makeB > PackageSample.java】
package makeB;
public class PackageSample {
public void show(){
System.out.println("makeBパッケージです。");
}
}
2つの「PackageSample」という名前のクラスを作成します。通常ならクラス名の重複はエラーになりますが、パッケージを別にすることで同じクラス名でも作成することができます。
package パッケージ名;
どのパッケージに属するかは、ソースファイルの先頭に「package」キーワードで宣言します。パッケージを宣言しない場合はデフォルト・パッケージに属します。サンプルでは「makeA」と「makeB」という別のパッケージに属性しているのでクラス名の重複があってもエラーになりません。
パッケージの参照
【Sample.java】
public class Sample{
public static void main(String[] args) {
makeA.PackageSample makeA_Obj = new makeA.PackageSample();
makeB.PackageSample makeB_Obj = new makeB.PackageSample();
makeA_Obj.show();
makeB_Obj.show();
}
}
makeBパッケージです。
パッケージ名.クラス名 ○○ = new パッケージ名.クラス名();
パッケージのクラスを参照するには、クラス名の前に「パッケージ名+ドット」をつけます。どのパッケージに属するどのクラスと指定するわけです。呼び出し元と呼び出し先が同じパッケージに属しているならば、「パッケージ名+ドット」は省略できます。
単純名と限定名
import makeA.PackageSample;
public class Sample{
public static void main(String[] args) {
makeA.PackageSample Obj1 = new makeA.PackageSample();
PackageSample Obj2 = new PackageSample();
Obj1.show();
Obj2.show();
}
}
makeAパッケージです。
単純名とは「単一の識別子のみで構成される名前」のことです。簡単に言えば「パッケージ名+ドット」がなくクラス名だけで記述するのが単純名で、「パッケージ名+ドット」付きで書くのが限定名です。
呼び出し元と呼び出し先が同じパッケージに属しているならば、「パッケージ名+ドット」は省略できました。呼び出し元で呼び出し先をインポートすることで同様なことができます。
import パッケージ名.*;
import パッケージ名.クラス名;
クラスをインポートするには、importキーワードを使います。「パッケージ名・クラス名」で特定のクラスのみをインポートすることができますし、「パッケージ名・*」 とアスタリスクで指定するとそのパッケージに属する全てのクラスがインポートされます。
import makeA.PackageSample;
1行目でmakeAパッケージのPackageSampleクラスをインポートしました。これでデフォルトパッケージに属するSampleクラスからでも「パッケージ名+ドット」のない単純名で参照することができます。
makeA.PackageSample Obj1 = new makeA.PackageSample(); PackageSample Obj2 = new PackageSample();
4行目は限定名でインスタンスを生成していますが、5行目は単純名でインスタンスを生成しています。同じクラスなのでメソッドの結果も当然同じです。
同名クラスをインポート
import makeA.PackageSample;
import makeB.PackageSample;
public class Sample{
public static void main(String[] args) {
}
}
パッケージmakeAのPackageSampleクラスとパッケージBのPackageSampleクラスをインポートしてみます。結果はエラーになります。同名のクラスを指定してインポートできません。
import makeA.*;
import makeB.*;
public class Sample{
public static void main(String[] args) {
PackageSample Obj = new PackageSample();
}
}
Exception in thread "main" java.lang.Error: Unresolved compilation problem
型 PackageSample はあいまいです
アスタリスクを使ってパッケージ全体をインポートすると、クラス名が重なってもエラーにならずにインポートできます。しかしクラスを参照するときは単純名ではできません。単純名ではどのパッケージのクラスなのかわからない為、一意になるように限定名で参照します。
|
|
クラスメソッド
前回はクラス変数についてみました。今回はクラスメソッドについてみていきます。
クラスメソッドとは
※wikipedia引用
クラスメソッド (class method) とはクラスに属するメソッドのことであり、インスタンスを生成せずにクラスから直接呼び出すことができる。基本的に、その振る舞いは非オブジェクト指向言語における関数と変わらない。
クラス変数と考え方は同じです。1つのクラスから複数のインスタンスが生成できます。インスタンスメソッドを参照するときは、どのインスタンスのメソッドなのか指定して参照します。同様にクラスメソッドの場合は、どのクラスのメソッドなのか指定して参照します。インスタンスメソッドは各インスタンスに属するのに対し、クラスメソッドはクラスに属します。

クラスメソッドの宣言
【StaticSample.java】
public class StaticSample {
static void method_1(){
System.out.println("クラスメソッドです。");
}
void method_2(){
System.out.println("クラスメソッドではありません。");
}
}
「StaticSample」クラスでは2つのメソッドがあります。メソッドは基本的にインスタンスが生成されると、そのインスタンスに属するインスタンスメソッドとなりますが、あるキーワードを付けることによりクラスメソッドにすることができます。
static void method_1(){
static 返却値の型 クラスメソッド名{ ・・・}
「static」キーワードをメソッド宣言時につけることによりクラスメソッドとなり、クラスに属するメソッドとなります。
クラスメソッドの参照
【Sample.java】
public class Sample{
public static void main(String[] args) {
StaticSample.method_1();
}
}
3行目でクラス名を指定してメソッドを参照しています。クラスに属しているので直接クラスから参照できます。数学の公式を計算をするメソッドなど、いちいちインスタンスを生成せず「非オブジェクト指向言語における関数」のように使いたい場合に便利です。
では、クラスメソッドでない「method_2」メソッドをクラスを指定して直接参照するとどうなるかみてみます。
StaticSample.method_2();
Exception in thread "main" java.lang.Error: Unresolved compilation problem
型 StaticSample の非 static メソッド method_2() を static 参照することはできません
結果はエラーになります。クラスメソッドでないメソッドは、インスタンス生成後にインスタンスメソッドとなります。各インスタンスに属するメソッドなのでクラス指定では参照できません。
クラスメソッドの注意点
public class StaticSample {
int field;
static void method(){
this.field = 100;
}
}
クラスメソッドはクラスメソッドに属してるので、クラスメソッドの処理の中にインスタンスに属する変数は書けません。サンプルではクラスメソッドの中で変数fieldを使っていますがこの変数はインスタンス後にインスタンス変数になります。クラスに属するメソッドにインスタンスに属する変数が混ざるのでエラーになります。
Exception in thread "main" java.lang.Error: Unresolved compilation problem
static コンテキストでは this を使用できません
クラスに属するクラス変数なら使うことができます。
|
|
クラス変数
今回はクラス変数についてみていきます。
クラス変数とは
※wikipedia引用
クラス変数(class variable)とは、同一クラス・派生クラスで共有される変数である。 そのため、関連クラスに渡って共通に使用できる大域変数(グローバル変数)であるともいえる。
これに対して、インスタンスごとに確保される変数のことを、インスタンス変数あるいは単にフィールド (計算機科学)、データメンバ、メンバ変数などと呼ぶ。
1つのクラスから複数のインスタンスを生成できます。インスタンス変数を参照するときは、どのインスタンスの変数なのか指定して参照します。同様にクラス変数の場合は、どのクラスの変数なのか指定して参照します。インスタンス変数はインスタンスごとに独立して確保される変数に対し、クラス変数はクラスごとに確保される変数です。
クラス変数の宣言
【StaticSample.java】
public class StaticSample {
static int allPageNo = 0;
int pageNo;
StaticSample(int pageNo){
this.pageNo = pageNo;
allPageNo++;
}
void displayPage(){
System.out.println(this.pageNo + "/" + allPageNo);
}
}

「StaticSample」クラスでは2つのフィールド宣言があります。フィールドは基本的にインスタンスが生成されると、そのインスタンスで独立した変数となりますが、あるキーワードを付けることによりクラス変数にすることができます。
static int allPageNo = 0;
static 型 クラス変数名
「static」キーワードをフィールド宣言時につけることによりクラス変数となり、クラス自身が確保する変数となります。
allPageNo++;
サンプル「StaticSample」クラスでのクラス変数の処理ですが、コンストラクタ内で「+1」しています。つまりインスタンスの生成ごとに「+1」されるので,このクラスから生成したインスタンスの数を表しています。
【Sample.java】
public class Sample{
public static void main(String[] args) {
StaticSample page1 = new StaticSample(1);
StaticSample page2 = new StaticSample(2);
StaticSample page3 = new StaticSample(3);
page1.displayPage();
page2.displayPage();
page3.displayPage();
}
}
2/3
3/3
3行目で1つ目のインスタンスを生成しています。この時点でクラス変数「allPageNo」は1足され値は「1」となっています。
4行目で2つ目のインスタンスを生成しています。この時点もクラス変数「allPageNo」は1足され値は「2」となっています。
5行目も同様です。クラス変数「allPageNo」の値は「3」になります。
結果をみれば、クラス変数「allPageNo」の値は「3」になっていることがわかります。
クラス変数の参照
【StaticSample.java】
public class StaticSample {
static int allPageNo = 0;
int pageNo = 0;
}
【Sample.java】
public class Sample{
public static void main(String[] args) {
System.out.println(StaticSample.allPageNo);
}
}
クラス変数はクラス自身が持つ変数です。ですのでインスタンスを生成しなくても直接クラスを指定して参照することができます。
クラス名.クラス変数名
では、クラス変数でないpageNoフィールドをクラスを指定して直接参照するとどうなるかみてみます。
System.out.println(StaticSample.pageNo);
Exception in thread "main" java.lang.Error: Unresolved compilation problem
非 static フィールド StaticSample.pageNo を static 参照できません
結果はエラーになります。クラス変数でないフィールドは、インスタンス生成後にインスタンス変数となります。インスタンスごとに確保される変数なのでクラス指定では参照できません。
|
|
インターフェース (3) 多重継承
今回はインタフェースによる多重継承をみていきます。
多重継承とは
複数のクラスから継承することを多重継承といいます。Javaでは複数のクラスからの多重継承は認められていません。クラスの多重継承が認められれば、スーパークラスのメンバに同じ名前があった場合、「どちらのメンバを継承するのか」などややこしい問題が出てきます。
それに対してインターフェースは、メソッドの宣言だけを行い具体的な処理がない抽象メソッドでした。具体的な処理はインターフェースの実装クラスで記述するので、同じメソッド名を継承しても問題ありません。
クラスとインターフェースの継承(1)
【SuperClass.java】
class SuperClass{
void method(){
System.out.println("スーパークラス : メソッド");
}
}
【InterfaceSample.java】
interface InterfaceSample {
void method2();
}
【SubClass.java】
class SubClass extends SuperClass implements InterfaceSample{
//メソッド
public void method2(){ //オーバーライド
System.out.println("サブクラス : メソッド");
}
}

クラスとインタフェースを同時に継承しています。class宣言のときに「extends」と「implements」の両方のキーワードを用いるわけですが、「extends」の方を先に書かないと構文エラーになります。
class サブクラス名 extends スーハー゚クラス名 implementes インターフェース名
インターフェースのメソッドは抽象メソッドなのでオーバーライドする必要があります。抽象メソッドは具体的な処理が記述されていないメソッドであり、実装クラスでオーバーライドして具体的な処理を記述することを強制しています。
【Sample.java】
public class Sample{
public static void main(String[] args) {
SubClass obj = new SubClass();
obj.method();
obj.method2();
}
}
サブクラス : メソッド
4行目はスーパークラス「SubClass」から継承してそのまま使っています。
5行目はインターフェース「InterfaceSample」から継承したメソッドをサブクラス「SubClass」でオーバーライドしています。
インターフェースのメソッドは実装クラスでオーバーライドしないといけないので多重継承としては少し微妙ですが、一応Javaでの多重継承となります。インターフェースの性質上、インターフェースは「実装クラスで宣言しなければならない最低限のメソッドを指示している」と考えた方がわかりやすいですが。。。
|
|
インターフェース (2) 定数
前回はインターフェースの概要と基本的な使い方をみました。今回はインターフェースのフィールドについてみていきます。
定数とは
※「Wikipedia」から引用します。
プログラミングにおいて定数とは、変数同様プログラムのソースコードにおいて、扱われるデータを一定期間記憶し必要なときに利用できるようにするために、データに固有の名前を与えたものである。 ただし変数とは異なり、一度初期化するとその内容を変更することはできない。
変数と似ていますが、代入されている値が変化するか固定かの違いです。
クラスと定数
【Constant.java】
public class Constant {
final int CONSTANT = 100;
}
まずはクラスでの定数です。クラスのフィールドを定数にしたい場合は、定数名の前に「final」キーワードをつけます。
final 型 定数名
定数にすると代入した値を変更できなくなります。javaでは大文字にするのが慣例です。
【Sample.java】
public class Sample {
public static void main(String[] args) {
Constant obj = new Constant();
obj.CONSTANT = 200;
}
}
Exception in thread "main" java.lang.Error:
Unresolved compilation problem:
final フィールド Constant.CONSTANT には代入できません
4行目で定数の値を変更しようとしました。定数は値を変更できないのでエラーになります。
インターフェースと定数
【InterfaceConst.java】
interface InterfaceConst {
int CONSTANT = 100;
}
インターフェースでフィールドを宣言しました。「CONSTANT」の宣言には「final」がありません。クラスでは「final」がなければ定数ではなく変数となり、値を自由に変更することができました。インターフェースではどのようになるかみてみます。
【Sample.java】
public class Sample implements InterfaceConst{
public static void main(String[] args) {
InterfaceConst.CONSTANT = 200;
}
}
Exception in thread "main" java.lang.Error:
Unresolved compilation problem:
final フィールド InterfaceConst.CONSTANT には代入できません
「final」キーワードをつけていないのに、エラーメッセージをみてみると「CONSTANT」はfinalフィールドであると言っています。つまりCONSTANTは定数扱いされているので値を変更できないためエラーになります。なぜこのようになるかというと、
インターフェースのフィールドは 「public static final」 に自動的になる
からです。よって「final」を指定しなくても「final」に自動的になっているため値を変更しようとするとエラーになります。
インターフェースフィールドの参照
【InterfaceConst.java】
interface InterfaceConst {
int CONSTANT = 100;
}
【Sample.java】
public class Sample implements InterfaceConst{
public static void main(String[] args) {
System.out.println(InterfaceConst.CONSTANT);
System.out.println(CONSTANT);
}
}
100
インターフェースのフィールドは、3行目のようにインターフェース名を指定して参照することもできますし、4行目のようにインターフェース名を省略して参照することもできます。
