[目次 ]
java言語はSun Microsystems, Inc から1995年に発表された。 しかし、現在はSunを2010年に買収したOracleからjavaの開発環境が提供されています。
現在、javaは利用目的に応じて以下のような複数の edition がある
※ここで紹介しているのは標準版のSEです
※javaVMなどの実行環境が普及しているので、他の言語にもバイトコードへのコンパイルを行うものが増えている。さらに、様々なスクリプト言語の実行環境としてjavaの実行環境を利用する動きもある。
同じソースコードやバイトコードが実行環境によらず何処でも安心して使えるように作られている。
[目次 ]
基本データ型は変数用に確保したメモリに直接に値が格納されるデータ型。データの形式は実行環境によらず一意に決められている。
参照データ型はオブジェクトの参照を格納するデータ型。基本データ型以外のデータ(配列、文字列の様なデータ)は全てオブジェクトに格納され、オブジェクトの参照を用いてのみ利用可能。
※参照はC言語のポインターに相当するものだが、以下のような点で異なる
[目次 ]
処理中に例外的状況になり処理の続行が不可能になった場合、別の場所に書かれた例外処理に直ちに移行する仕組みが用意されてい る。処理中のメソッドから脱出することも可能で例外処理を呼び出し側のメソッド内に記述可能。
例外(Exception)を投げる(throw)と、例外に対応するcatchに 処理が移行する。メソッド内に例外を捕まえる構文が無い場合はメソッドを呼び出した側に戻る。ここで、例外発生で戻る可能性が有るメソッドはそのことをthrows Exceptionと予め宣言する必要がある。
public void doSomthing() throws Exception{//例外を投げる関数は必ず投げる例外の種類を宣言する
.......
if(file==null)throw new Exception();//例外が発生したらExceptionを投げる ....... }
returnやthrowでメソッドから戻るときに必ずこれだけは実行してほしい処理がある場合にはfinallyの構文を使 う
finally{メソッドから戻る時に実行したい処理プログラム}
例外を投げてメソッドから戻る場合でもこのfinally部分は必ず戻る前に実行する。
例外を捕まえる場合、try catchの構文を使う。
try{ ... // ここで例外が発生すると Exceptionを継承した例外クラスのインスタンスを生成して投げる // 例外インスタンスに対応したcatch()へ処理が移行する // catchのブロックでは例外の情報をインスタンスから読み取って適切な例外の処理を行う。 ... }catch(IOException e){ //例外がIOExceptionならここで処理 e.printStackTrace();//とりあえずこう書いておけば例外の発生場所を書き出す }catch(Exception e){ //例外がExceptionならここで処理 e.printStackTrace(); }//catchの部分は例外の種類に応じていくつでも書けます
※例外にも種類が有るり、Exceptionはもっとも一般的な例外。 Exceptionを継承した例外を投げたり、捕まえたりできる。
[目次 ]
オブジェクト(object)は「太郎さん」や「太郎さんの車」のように他と区別しできるまとまった「もの」のことです。必ずしも物体である必 要はありません。「鹿児島市役所」のような社会的な仕組みもオブジェクトとして捉えることができます。
大規模ソフトウエアの開発は一度に行うのは不可能です。このため、先ず仕事の分割を行い、個々に開発を行った後で組合わせて1個 のシステムに組み上げます。
プログラミングで言うオブジェクト(object)とは、上記の役割に伴う変数や関数をまとめた単位です。 オブジェクト内のこれら変数や関数をまとめてメンバ(member)、変数をフィールド(field)、関数をメソッ ド(method)と呼びます。
さらに、メンバには責任を果たすために外部に公開(public)されるものとオブジェクト内に使用を限定する非公開(private)のもなどに区別されます。この様にメンバには外部から見えるものと見えないものがあり、この性質を可視性と
呼びます。可視性はメンバの重要な特性です。公開メンバを変更すればオブジェクト外にも影響を与えます。しかし、非公開の部分は変更しても外部へ影響を与えません。
受付係 |
<<変数;フィールド>> −年齢 −性別 −社員連絡先リスト −来訪者リスト ... |
<<関数;メソッド>> +来訪取次の依頼 +電話番号の問い合せ ・・・ |
可視性には自クラスのみで使えるprivate、自クラスを継承したクラスでも使えるprotected、パッケージ内から使えるpackage 、そしてどこからでも使えるpublicの4種類が用意されています。
以下にUMLに定義された可視性とjava言語の対応を示します。protectedやpackageについては後で説明します。
UMLでの可視性 UMLでの略号 java言語での表記 java言語での意味 public + public 公開(外部に公開) private - private 非公開(自クラスとそのインスタンスにのみ公開) protected # protected javaでは継承先に加えて同じパッケージ内に公開
UMLでは継承先にのみ公開package ~ 指定無(既定値) 同じパッケージ内にのみ公開
UML(Unified Modeling Language)はオブジェクト指向の開発で使われる図式の統一を目指して公開されたものです。下記に関連URLを示す
UMLTM Resource Page http://www.omg.org/uml/
[目次 ]
java言語では、クラスにオブジェクトのメンバ構成を示し、これを元に同じ構造のオブジェクトを複数生成できるようにしています。(クラスベースのオブジェクト指向言語)
このクラスを元に生成されるオブジェクトをインスタンス・オブジェクトと呼びます。
さらに、java言語ではクラスも自分のメンバを持つことができます。クラスも1つのオブジェクトと言えるので、これをクラス・オブジェクトと呼ぶことにします。
クラスにはクラス・メンバとインスタンス・メンバが記述できます。クラス・メンバはプログラムの起動時から実体があります。しかし、インスタンス・メンバはインスタンスが生成されたときに初めて実体が作られます。
「クラス」という言葉は 辞書を引くと分類されたもの、類、部類 の意味です。
オブジェクト指向のモデルのクラスは,オブジェクトをクラス分けしたものです。
※分類は多様に行えます。人は哺乳類に分類できるし,性別や仕事上の役割でもクラス分けできます。子供や大人など時間経過でクラスが変わることもあり得ます。
java言語のクラスは,インスタンスメンバの構造を定義して,これを元に同じ構造のインスタンスを複数作れるようにしています。従って,すべてのインスタンスは,その元になったクラスに分類できます。しかし,受付係クラスのインスタンス「花子さん」「太郎さん」は受付係クラスに分類できますが、女性クラスや男性クラスに分類できません。時間経過で所属クラスが変わる子ともありません。
※javaではインスタンス(オブジェクト)は所属するクラスを変更できない
java言語のクラスはクラスのメンバを持つことができるので、クラス自体を一つのオブジェクトとみなすことも可能です。
クラスのメンバはstaticを付けることで示されます。
javaのApplicationを起動するmainメソッドにはstaticが付いています。起動時にはまだインスタンスは作っていないので、インスタンスのメンバは使えません。しかし、クラスのメンバはクラスをメモリーに読み込むとメンバの実体がメモリー上に作られるので、起動時に参照することができます。
※java.lang.Mathクラスのようにクラス・メンバのみを持つクラスもあります。
HelloWorldプログラムではstaticを付けることでmainメソッドがクラス・メンバであることを示しています。
/*javaのHelloWorld*/
public class HelloWorld{
public staitc void main(String args[]){
System.out.println("Hello World!");
}
}
ここで、HelloWorldクラスの構造はUMLでは下図の様に表わします。
HelloWorld
+main(args:String[ ])
※メンバに下線 を引くことでクラス・メンバであることを示します。
インスタンスは辞書では 事例、例、(事実を例証するための例)と説明されている。
java言語ではインスタンスはクラスに記述されたインスタンス・メンバに従って作られます。従って,クラスの型に従うオブジェクトの1例ではあります。
C言語では新しいデータ型を構造体で定義し,構造体型の変数をプログラムの中で作れました。構造体をjavaのクラスに変数をインスタンスに対応させると,よく似た関係であることが分ります。
※構造体に比べ,クラスはメンバに関数をもてること,クラスメンバも持てること,メンバの可視性が指定できること,など色々と拡張されています。
インスタンスを生成する際、オブジェクトが不正な内容を持たないように初期化するメソッドがある。この様なメソッドをコンストラクタと言う。 java言語ではコンストラクタはクラスと同じ名前で戻り値を書かないメソッドとしてクラスの中に記述する。
クラスにコンストラクタが記述されていない場合は、コンパイラがなにもしない引数無しのコンストラクタを追加する。従って、クラスには必ずコンストラクタ が存在する。
※次のプログラム例のように、メソッドは名前と引数並びで区別されるので、コンストラクタも引数並びを変えることで複数定義できる。
public class Complex
{
/*−−−−インスタンスの雛形−−−−*/
//インスタンスのもつデータ型と名前
private double re;//実部
private double im;//虚部
//コンストラクタ インスタンス生成時に初期化を行うメソッド
public Complex(double r, double i) { re=r;im=i; } //引数並びを変えれば複数のコンストラクタを定義できる public Complex(double r) { re=r;im=0; } // public void print() { if(im>=0)System.out.printf("%lf +%lfI",re,im); else System.out.printf("%lf %lfI",re,im); } /*テスト用のメイン関数*/ static public void main(String arg[]) { Complex z=new Complex(1,2);//インスタンスの生成と参照変数の初期化 z.re=2;//インスタンスメンバの参照 z.print();//インスタンスメンバの参照 z=null;//参照を切る。この行は実は不要。zが自動変数なのでメソッドから出ると参照は切れる。 } }
花子さんを受付係クラスのインスタンスとして
生成すると、花子さんが受付係りから会計係りに移動することができない。
この為に、所属が変化する状況を表現するにはプログラミングにおいて工夫が必要となる。
(社員クラスのインスタンスとして花子さんを生成し、社員のフィールドに役割に応じた振る舞いを示す「係り」を持つ形にして、係りに受付係りを代入すると
受け付けの仕事を行い、会計係りを代入すると会計の仕事を行うなど...)
社員 <<変数;フィールド>>
−名前
−年齢
−性別
−係り
...<<関数;メソッド>>
+配置替(係り)
・・・
[目次 ]
プログラム中に多数のクラスが存在すると、その関係はクラスの組合わせの数に応じて複雑になってしまいます。クラスを抽象化してまとめることができれば複雑な関係を整理して単純化できます。実際、人間は抽象化により情報の処理を共通化し簡単にしています。たとえばスポーツカー、ワゴン車、トラックの様な異なるクラスのオブジェクトを、全て一般化した自動車クラスのオブジェクトとして取り扱えば、考えることは少なくて済みます。
スポーツカー、ワゴン車、トラックは異なるクラスのインスタンスですが、これらの構造の共通部分を取り出して一般化した自動車クラスを作ることで、全て自動車クラスに何かを付け加えて特殊化したものとなります。
この様な一般化の利点はスポーツカー、ワゴン車、トラックを全て自動車クラスのオブジェクトと見なして扱えることです。なぜなら、自動車オブジェクトのメンバはスポーツカー、ワゴン車、トラックの共通部分ですから、共通部分のフィールド参照も、メソッド呼び出しも保証されます。
この様な一般化を汎化といいます。汎化は生物の種を系統樹で階層的に分類するのと同様な分類構造を可能にします。
汎化 一般化−特殊化 A is a B (AはBの一種)
汎化はこれから説明するクラス継承の機能を用いて表現できます。
構造が全く異なるオブジェクトでも、共通の操作が可能なものとして分類できる場合があります。例えば、飛行機、熱気球、鳥、トンボなどはいずれも飛ぶことができます。もちろん構造が異なるので飛び方は様々です。
java言語では、このような操作の共通性による分類を可能にするために、クラスに似たものとしてインターフェイスを用意しました。インターフェイスはインスタンス・メソッドの名前と引数並びをまとめたものです。クラスを作るときにインターフェイスの実装を宣言すると、クラスのインスタンスがインターフェイスに定義されたメソッドを実装することが保証されます。
インターフェイスを実装したインスタンスは、操作の共通性が在るため、インスタンス型の変数にその参照を代入することが可能です。
クラス継承は単一継承しか許されませんが、インターフェイス実装は多重実装が可能なので、様々な分類に対応可能です。
javaでは既存のclassを継承し、新たな要素を加えて新しいclassを作ることができます。Tenクラスを継承して半径を加えて Maruクラスを作る場合を下図に示します。継承では加える部分のみを記述すれば十分です。さらに、上書きが可能ですからメソッドの動作を変更することも できます。
javaVMはMaruクラスを実行するとき継承元のTenクラスを自動的に読み出して使います
java言語の継承は単一継承です。単一継承は継承元を1個しか持てません。
※C++言語は複数のクラスを継承する多重継承を認めています
java言語では参照データ型の変数には、継承先クラスのインスタンスの参照も代入可能
継承元が持っているメンバを継承先のインスタンスも必ず持っているので、インスタンスのメソッド呼び出しやフィールド参照が保証される為です。
java言語のクラスは継承元を書かないと
java.lang.Objectを継承します
この結果、全てのインスタンスはObjectを参照する変数に代入できます。
インターフェイスは実装方法を指定せずにインスタンスの外部との窓口を定義したものです。ここで窓口といったのはメソッドのシグネチャ(戻り値、名前、引数並び)のことです。書式はclassと同様ですがメンバは公開の抽象メソッドと公開の定数フィールドのみです。
データ構造とアルゴリズムの講義では、操作のみでデータ構造を定義する例としてスタックが出てきたと思いますが、インターフェイスを使えば次のように定義できます。
abstract interface Stack { //抽象メソッドのみ public abstract Object pop();//オブジェクトをスタックから取り出す public abstract void push(Object o);//オブジェクトをスタックに積む } /*灰色の部分は省略するのが普通*/
※インターフェイスのメンバはpublicの抽象メソッドとpublicの定数のみなのでpublicやabstractは省いて記述します。
インターフェイス型の参照変数を作ることができ、インターフェイスを実装したインスタンスの参照を代入できます。この結果、インターフェイスを実装した異 なるクラスのインスタンスを、インターフェイスの共通性でまとめて扱うことが可能になります。
単一継承しか許さない継承に比べ、インターフェイスは多重実装が可能なので、このような使い方が自由に行える。
※java8からはインターフェイスに デフォルトの実装を記述できる。
[目次 ]
オブジェクトは関連性の強い関数とデータをまとめたモノです。
オブジェクトの中身へのアクセスは公開部分にのみ可能です。
この様 に、関数やデータを一つにまとめアクセス管理機能を付けることをカプセル化と 呼びます。
オブジェクトの構造(関数やデータ)を記述するクラスが 存在し、クラスを雛形としてオブジェクトをクラスのインスタンスとして複数生成する言語をクラスベースのオブジェクト指向言語と呼んでいます。
※C++やjava言語はクラスベースのオブジェクト指向言語です。
さらに、クラスを階層的に分類する継承の仕組みを用意することも複雑なシステムを単純化して解り易くする上で欠かせません。
これらのことから、以下の3つの機能を備えた言語をオブジェクト指向言語と呼ぶことが多い。
- カプセル化
- クラス
- 継承
※これらの仕組みは、オブジェクト指向のモデルから出てきたと言うよりも、大規模プログラミングの複雑さを軽減する必要性から出てきたものです。
[目次 ]