1.1 Javaの概要

オブジェクト指向プログラミング言語の選択肢として、Javaがあります。Javaの重要な概念は次のとおりです。

  • Java仮想マシン(JVM)。プラットフォームの独立性を確保するための基礎を提供します。

  • 自動ストレージ管理機能。ガーベージ・コレクションなどがあります。

  • C言語の構文に類似した言語構文。

このような概念から、オブジェクト指向で、アプリケーション・プログラムを効率的に作成できる言語が開発されました。

この項の内容は次のとおりです。

1.1.1 Javaおよびオブジェクト指向プログラミングの用語

次の用語は、Oracle Database環境におけるJavaアプリケーション開発でよく使用される用語です。

1.1.1.1 クラス

クラスの概念は、どのオブジェクト指向プログラミング言語でもサポートされています。表定義のように、クラスでは、共通の特性を持つオブジェクトのテンプレートが提供されます。各クラスで、次の項目を定義できます。

  • フィールド

    フィールドは、特定クラスの各オブジェクト(インスタンス)に存在する変数、または、グローバルですべてのインスタンスに共通な変数です。インスタンスのフィールドは、リレーショナル表の行の列に類似しています。クラスによって、フィールドと各フィールドの型が定義されます。

    Javaでは、フィールドをstaticとして宣言できます。staticとして宣言されたクラスのフィールドはグローバルであり、そのクラスのすべてのインスタンスに共通です。Javaランタイムの特定のインスタンス内の静的フィールドに対して、特定の時点の値は1つのみです。staticとして宣言されないフィールドは、そのクラスの各インスタンス内で個別の値として作成されます。

    publicprivateprotectedおよびデフォルト・アクセス修飾子では、アプリケーションのフィールドの範囲が定義されます。Java言語仕様(JLS)では、すべてのフィールドに対するデータの可視性規則が定義されます。可視性規則では、これらのフィールド内のデータにどのような場合にアクセスできるかが定義されます。

    図1-1の例では、従業員識別子がprivateとして定義されており、これは、他のオブジェクトがこのフィールドに直接アクセスできないことを示しています。この例で、オブジェクトがidフィールドにアクセスするには、getId()メソッドをコールします。

  • メソッド

    メソッドは、クラスに関連付けられたプロシージャです。フィールドと同様に、メソッドをstaticとして宣言でき、この場合、グローバルにコールできます。メソッドをstaticとして宣言しない場合、そのメソッドはインスタンス・メソッドで、オブジェクトがクラスのインスタンスである場合のオブジェクト上の操作としてのみコールできることを示しています。

    フィールドと同様に、メソッドは、publicprivateprotectedまたはデフォルト・アクセスとして宣言できます。この宣言では、メソッドをコールできる範囲が定義されます。

1.1.1.2 オブジェクト

Javaオブジェクトはクラスのインスタンスであり、リレーショナル表の行に類似しています。オブジェクトはデータ値の集まりで、クラスの非静的フィールド定義によって記述される個々の要素です。

図1-1に、2つのフィールドid(従業員識別子)とlastName(従業員の姓)、およびgetId()メソッドとsetId(String anId)メソッドで定義されているEmployeeクラスの例を示します。idフィールドはprivateであり、lastNameフィールド、getId()メソッドおよびsetId(String anId)メソッドはpublicです。

図1-1 クラスとインスタンス

図1-1の説明が続きます
「図1-1 クラスとインスタンス」の説明

インスタンスを作成すると、フィールドには、ある従業員にのみ関係する個人のプライベートな情報が格納されます。つまり、1つの従業員インスタンスに含まれる情報は、該当する特定の従業員のみが認識しています。図1-1の例は、Employeeクラスの2つのインスタンスを示しており、1つは従業員Smith用、もう1つはJones用です。各インスタンスには、個々の従業員に関連する情報が含まれています。

1.1.1.3 継承

継承は、オブジェクト指向プログラミング言語の重要な機能です。これによって、クラスは他のクラスのプロパティを含めることができます。プロパティを継承するクラスは子クラスまたはサブクラスと呼ばれ、プロパティの継承元のクラスは親クラスまたはスーパークラスと呼ばれます。この機能は、定義済コードの再利用にも役立ちます。

図1-1の例では、Employeeクラスのプロパティを継承するFullTimeEmployeeクラスを作成できます。継承されるプロパティは、スーパークラスの各フィールドおよびメソッドに対して宣言されている接続修飾子によって決まります。

1.1.1.4 インタフェース

Javaでは単一の継承のみがサポートされ、つまり、各クラスは、1つのクラスからのみフィールドおよびメソッドを継承できます。複数のソースからプロパティを継承する必要がある場合、Javaは複数継承の形式のインタフェースの概念を提供します。インタフェースはクラスに類似しています。ただし、メソッドのシグネチャのみが定義され、実装は定義されません。インタフェースで宣言されたメソッドはクラスで実装されます。1つのクラスで複数のインタフェースを実装すると、複数継承が行われます。

1.1.1.5 カプセル化

カプセル化は、データとメソッドを他から隠すオブジェクトの機能を示し、オブジェクト指向プログラミングの基本原理の1つです。Javaでは、クラスによって、フィールド(オブジェクトの状態を格納)およびメソッド(オブジェクトのアクションを定義)がカプセル化されます。カプセル化によって、再利用可能なプログラムを作成できます。また、publicと宣言されたオブジェクトの機能にのみアクセスを制限することもできます。その他のすべてのフィールドおよびメソッドはprivateであり、内部的なオブジェクト処理に使用できます。

図1-1の例では、idフィールドがprivateであり、これへのアクセスは、それを定義しているオブジェクトに制限されます。他のオブジェクトがこのフィールドにアクセスするには、getId()メソッドを使用します。カプセル化を使用すると、getId()メソッドをprivateとして宣言するか、またはgetId()メソッドを定義しないことによって、idフィールドへのアクセスを拒否できます。

1.1.1.6 ポリモフィズム

ポリモフィズムは、異なるオブジェクトが同じメッセージに対してそれぞれ異なる応答をするための機能です。オブジェクト指向プログラミング言語では、1つ以上のメソッドを同じ名称で定義できます。これらのメソッドは異なるアクションを実行し、異なる値を戻すことができます。

図1-1の例で、各種の従業員がそれぞれの給与累計で応答できるようにする必要があるとします。給与は、従業員の種類ごとに異なる方法で計算されます。

  • フルタイム従業員は賞与の支払対象です。

  • 適用対象従業員は時間外手当の支払対象です。

手続き型言語では、考えられるケースをそれぞれ定義して、次のようなswitch文を記述します。

switch: (employee.type)
{
  case: Employee
        return employee.salaryToDate; 
  case: FullTimeEmployee
        return employee.salaryToDate + employee.bonusToDate
  ...
}

新しい種類の従業員を追加する場合は、switch文を更新する必要があります。また、データ構造を変更する場合は、その構造を使用するswitch文をすべて変更する必要があります。Javaなどのオブジェクト指向言語では、Employeeクラスで定義されていない情報がサブクラスに含まれている場合、EmployeeクラスのサブクラスごとにメソッドcompensationToDate()を実装できます。たとえば、適用対象従業員のcompensationToDate()メソッドを次のように実装します。

public float compensationToDate()
{
  return (super.compensationToDate() + this.overtimeToDate()); 
}

フルタイム従業員の場合は、compensationToDate()メソッドを次のように実装できます。

public float compensationToDate()
{
  return (super.compensationToDate() + this.bonusToDate());
}

メソッド名を共通して使用することで、従業員の種類を指定しなくても、異なるクラスのメソッドをコールして、結果を取得できます。フルタイム従業員とパートタイム従業員を処理するために特別なメソッドを記述する必要はありません。

また、Employeeからプロパティを継承しないContractorクラスを作成し、このクラスにcompensationToDate()メソッドを実装することもできます。給与累計の合計を計算するプログラムは、フルタイム、パートタイム、契約社員のいずれであるかに関係なく給与計算時に全従業員に対して反復処理し、従業員ごとにcompensationToDate()メソッドをコールして戻された値を合算します。メソッドのコール元が正常に動作することを認識した上で、個々のcompensationToDate()メソッドまたはクラスを安全に変更できます。

1.1.2 Java言語の主な機能

Java言語には、サーバー・アプリケーションの開発に最適な機能がいくつかあります。次の機能があります。

  • 簡潔性

    Javaでは、オブジェクト・モデルが一貫して規定されているため、サーバー・アプリケーションの作成で使用される他のほとんどの言語より単純です。大規模なクラス・ライブラリの標準セットは、あらゆるプラットフォームのJava開発者が強力なツールとして使用できます。

  • 移植性

    Javaはプラットフォーム間で移植可能です。Javaでは、プラットフォームに依存するコードを記述でき、複数のシステム間でシームレスに移植するプログラムも容易に作成できます。

  • 自動ストレージ管理

    JVMでは、プログラムの実行中にすべてのメモリー割当てと割当て解除が自動的に実行されます。Javaプログラマは、新規オブジェクトに対するメモリーの割当てや、参照されなくなったオブジェクトに対するメモリーの解放を明示的に行うことはできません。かわりに、これらの操作はJVMに依存して実行されます。メモリーの解放処理は、ガベージ・コレクションと呼ばれます。

  • 強い型指定

    フィールドを使用するには、そのフィールドの型を宣言する必要があります。Javaの強い型指定によって、JavaアプリケーションとPL/SQLアプリケーション間における言語間のコールに対する適切で安全なソリューションが提供され、JavaコールとSQLコールが同じアプリケーション内に統合されます。

  • ポインタの不使用

    Javaの構文はC言語に類似していますが、ダイレクト・ポインタやポインタ操作はサポートされていません。プリミティブ型以外のすべてのパラメータは、値ではなく参照で渡します。この結果、オブジェクト識別性が保持されます。Javaでは、ポインタへの低水準の直接アクセスはサポートされていないため、メモリーの破損やリークを防ぐことができます。

  • 例外処理

    Java例外はオブジェクトです。Javaでは、開発者が、特定のクラスでメソッドによってスローされる例外を宣言する必要があります。

  • 柔軟なネームスペース

    Javaでは、クラスが定義され、そのクラスがインターネットのドメインのネームスペースを模倣した階層構造に格納されます。Javaアプリケーションは分散でき、名前の衝突を回避できます。Java Naming and Directory Interface (JNDI)などのJava拡張機能によって、複数のネーム・サービスを統合するためのフレームワークが提供されます。Javaのネームスペース・アプローチは非常に柔軟であるため、Oracleは、JLSに完全に準拠して、クラス名を解決するスキーマの概念を組み込むことができます。

  • セキュリティ

    JavaバイトコードとJVM仕様の設計によって、Javaバイナリ・コードのセキュリティを組込みメカニズムで検証できます。Oracle DatabaseとともにインストールされるSecurityManagerのインスタンスでは、Oracle Databaseのセキュリティと組み合せることによって、Javaメソッドをコールできるユーザーが判断されます。

  • リレーショナル・データベースへの接続性の標準

    Java Database Connectivity(JDBC)およびSQLJを使用すると、Javaコードで、リレーショナル・データベース内のデータに対するアクセスおよび操作ができます。Oracleには、ベンダーに依存しない移植性のあるJavaコードでリレーショナル・データベースにアクセスできるようにするドライバが用意されています。

1.1.3 Java仮想マシン

Javaソースは、他の高水準のコンピュータ言語と同様に、低水準のマシン命令にコンパイルされます。各命令サイズが一律に1バイトであるため、Javaでは、これらの命令はバイトコードと呼ばれています。Cなど他のほとんどの言語は、IntelまたはHPプロセッサに固有の命令など、マシン固有の命令にコンパイルされます。

コンパイル時に、Javaコードは、Java仮想マシン(JVM)によって実行される、プラットフォームに依存しない標準のバイトコード・セットに変換されます。JVMは、Javaコードを実行する特定のプラットフォーム用に最適化された個別のプログラムです。

図1-2に、プラットフォームの独立性が、Javaによってどのように保持されるかを示します。各プラットフォームには、オペレーティング・システムに固有のJVMがインストールされています。Javaバイトコードは、JVMを介して、プラットフォームに依存する適切な処理へと解析されます。

図1-2 Javaコンポーネント構造

図1-2の説明が続きます。
「図1-2 Javaコンポーネントの構造」の説明

Javaアプリケーションの開発では、Java言語で記述された事前定義のコア・クラス・ライブラリを使用します。Javaコア・クラス・ライブラリは、一般的な機能を提供する各パッケージに論理的に分割されています。基本言語のサポートはjava.langパッケージによって、I/Oサポートはjava.ioパッケージによって、ネットワーク・アクセスはjava.netパッケージによってそれぞれ提供されます。JVMとコア・クラス・ライブラリによって提供されるプラットフォームでは、Javaプログラマは、Javaをサポートするすべてのオペレーティング・システムで正常に実行されるアプリケーションを開発できます。この概念は、「1回作成すれば、どこでも実行可能(write once, run anywhere)」というJavaの考え方を推進するものです。

図1-3は、OracleのJavaアプリケーションがJavaコア・クラス・ライブラリの上部に位置し、Javaコア・クラス・ライブラリがJVMの上部に位置していることを示しています。OracleのJavaサポート・システムはデータベース内に配置されているため、JVMはオペレーティング・システムと直接対話するかわりに、Oracle Databaseライブラリと対話します。

図1-3 Oracle DatabaseのJavaコンポーネント構造

図1-3の説明が続きます
「図1-3 Oracle DatabaseのJavaコンポーネント構造」の説明

JavaおよびJVMの詳細は、Java言語仕様(JLS)およびJVM仕様を参照してください。JLSで構文やセマンティクスが定義され、JVM仕様では、アプリケーションを実行するシステムに必要な下位レベルのアクションが定義されます。さらに、JVM実装には、VMの実装者が仕様に従ってコンパイルしたかどうかを判断するための互換性テスト一式があります。このテスト一式は、Java Compatibility Kit (JCK)と呼ばれます。Oracle JVM実装は、JCKに完全に準拠しています。総合的なJava方針の一環として、公に規定された標準と、その標準への準拠を検証する簡単な方法によって、ベンダーはすべてのプラットフォームでJavaのサポートを統一できます。

1.1.4 Javaクラス階層

Javaでは、クラスは大規模なクラス階層内で定義されます。階層の最上部にObjectクラスがあります。Javaのすべてのクラスは、スーパークラスの継承連鎖内をさかのぼる過程で、あるレベルのObjectクラスを継承しています。クラスBがクラスAを継承している場合、クラスBの各インスタンスには、クラスBに定義されたすべてのフィールドとクラスAに定義されたすべてのフィールドが含まれます。

図1-4は、一般的なJavaのクラス階層を示しています。FullTimeEmployeeクラスには、Employeeクラスで定義されたidフィールドおよびlastNameフィールドがあります。これは、Employeeクラスから継承されているためです。また、FullTimeEmployeeクラスでは、FullTimeEmployeeにのみ含まれる別のフィールドbonusが追加されます。

クラスBのインスタンスでは、クラスAまたはクラスBのいずれかで定義された任意のメソッドをコールできます。例では、FullTimeEmployeeインスタンスでコールできるメソッドは、FullTimeEmployeeでのみ定義されたメソッド、およびEmployeeクラスで定義されたメソッドです。

クラスBのインスタンスは、クラスAのインスタンスのかわりに使用でき、継承は、コードの再利用性を改善するための、オブジェクト指向言語の別の強力な構成となります。動作と状態を定義するクラスを、階層内の適切な場所、しかもクラス・ライブラリの既存の機能を利用できる場所に作成できます。