「4.12.6. 型とクラスとインタフェース」の編集履歴(バックアップ)一覧はこちら

4.12.6. 型とクラスとインタフェース」(2012/09/11 (火) 16:10:24) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

*[[4. 型と値と変数]] **[[4.1. 型と変数の種類]] **[[4.2. プリミティブ型と値]] **[[4.3. 参照型と値]] **[[4.4. 型変数]] **[[4.5. 引数付き型]] **[[4.6. 型の抹消]] **[[4.7. 具象可能型]] **[[4.8. 未加工型]] **[[4.9. 交差型]] **[[4.10. サブタイプ化]] **[[4.11. 型の使用箇所]] **[[4.12. 変数]] ***[[4.12.1. プリミティブ型の変数]] ***[[4.12.2. 参照型の変数]] ***[[4.12.3. 変数の種類]] ***[[4.12.4. final変数]] ***[[4.12.5. 変数の初期値]] ***4.12.6. 型とクラスとインタフェース Javaプログラミング言語では、全ての変数や全ての式はコンパイル時に決定可能な型を持っています。型はプリミティブ型か参照型です。参照型にはクラス型やインタフェース型も含みます。参照型は[[クラス宣言>8.1. クラス宣言]]や[[インタフェース宣言>9.1. インタフェース宣言]]を含む型宣言によって導入されます。型という言葉をクラスやインタフェースを参照するのに用いることがしばしばあります。 Java仮想マシンでは、全てのオブジェクトはある特定のクラスに属しています。オブジェクトを生み出す[[作成式>15.9. クラスインスタンス作成式]]で書かれるクラスや、オブジェクトを生み出すのに&tt(){Class}オブジェクトのリフレクションメソッドが使用されるクラスや、[[文字列連結演算子+>15.18.1. 文字列連結演算子+]]で暗黙的に作成されるオブジェクトのための&tt(){String}クラスがあります。このクラスをオブジェクトのクラスと呼びます。オブジェクトはそのクラスのインスタンスであり、そのクラスの全てのスーパークラスのインスタンスです。 全ての配列もクラスに属しています。配列オブジェクトに対し&tt(){getClass}メソッドを呼び出すと配列のクラスを表す(&tt(){Class}クラスの)クラスオブジェクトを返します([[10.8.>10.8. 配列のためのClassオブジェクト]])。 変数のコンパイル時の型は常に宣言されており、式のコンパイル時の型はコンパイル時に決定可能です。コンパイル時の型は変数が実行時にとりうる値や式が実行時にとりうる値を正ゲインします。実行時の値が&tt(){null}ではない参照ならば、あるクラスのオブジェクトや配列を参照しています。そのクラスはコンパイル時の型と必ず互換性があります。 変数や式はコンパイル時の型がインタフェースであるかもしれません。インタフェースのインスタンスはありません。インタフェース型の変数や式はそのインタフェースを実装するクラスのオブジェクトを参照します([[8.1.5.>8.1.5. スーパーインタフェース]])。 時々、変数や式は"実行時の型"を持ちます。これは実行時の変数や式の値を参照する値が&tt(){null}ではないオブジェクトのクラスを参照します。 コンパイル時の型と実行時の型の間の一致は2つの理由から不完全です。: +実行時、クラスやインタフェースはJava仮想マシンによってクラスローダーを使いロードされます。どのクラスローダーもそれ自身のクラスやインタフェースを定義しています。結果として、2つのローダーが等価なクラスやインタフェース定義をロードすることが可能ですが、実行時には異なるクラスやインタフェースとなります。結果として、もしそれをロードするクラスローダーが一致しなければ、正しくコンパイルされたコードはリンク時に失敗するかもしれません。 &i(){&small(){詳しくは論文Dynamic Class Loading in the Java™ Virtual Machine、著者Sheng Liang、Gilad Bracha, Proceedings of OOPSLA '98、出版ACM SIGPLAN Notices、Volume 33、Number 10、1998年10月、ページ 36-44、およびThe Java™ Virtual Machine Specification, Java SE 7 Editionを参照してください。}} +[[型変数>4.4. 型変数]]と[[型実引数>4.5.1. 型実引数とワイルドカード]]は実行時に非具象可能です。結果として、実行時には同じクラスやインタフェースはコンパイル時に複数の[[引数付き型>4.5. 引数付き型]]で表されます。特に、与えられたジェネリック型宣言([[8.1.2.>8.1.2. ジェネリッククラスと型引数]]、[[9.1.2.>9.1.2. ジェネリックインタフェースと型引数]])のコンパイル時の呼び出しは全て単一の実行時の表現を共有します。 特定の状況下で、引数付き型の変数が引数付き型ではないオブジェクトを参照することが可能です。この状況は[[ヒープ汚染>4.12.2. 参照型の変数]]として知られています。変数は常に引数付き型を表すクラスのインスタンスであるオブジェクト参照します。 #divstyle(background-color:#f0f0ff;border:1px solid black;padding 4px){{{ &bold(){&aname(ex4.12.6-1,option=nolink){例4.12.6-1. 変数の型 vs オブジェクトのクラス}} interface Colorable { void setColor(byte r, byte g, byte b); } class Point { int x, y; } class ColoredPoint extends Point implements Colorable { byte r, g, b; public void setColor(byte rv, byte gv, byte bv) { r = rv; g = gv; b = bv; } } class Test { public static void main(String[] args) { Point p = new Point(); ColoredPoint cp = new ColoredPoint(); p = cp; Colorable c = cp; } } &i(){&small(){この例で:}} -&i(){&small(){&tt(){Test}クラスの&tt(){main}メソッドの局所変数&tt(){p}は&tt(){Point}型であり、初期値として&tt(){Point}クラスの新たなインスタンスを参照します。}} -&i(){&small(){同様に局所変数&tt(){cp}は&tt(){ColoredPoint}型であり、初期値として&tt(){ColoredPoint}クラスの新たなインスタンスを参照します。}} -&i(){&small(){変数&tt(){cp}の値を変数&tt(){p}に代入することで&tt(){p}は&tt(){ColoredPoint}オブジェクトへの参照を持ちます。これは&tt(){ColoredPoint}が&tt(){Point}のサブクラスのため許可されています。ゆえに&tt(){ColoredPoint}クラスは&tt(){Point}型と[[代入互換(assingment-compatible)>5.2. 代入変換]]です。&tt(){ColoredPoint}オブジェクトは&tt(){Point}の全てのメソッドをサポートしています。その特有のフィールド&tt(){r}、&tt(){g}、&tt(){b}に加えて、&tt(){Point}クラスのフィールド、すなわち&tt(){x}と&tt(){y}も持ちます。 -&i(){&small(){局所変数&tt(){c}はインタフェース型&tt(){Colorable}です。変数は&tt(){Colorable}を実装するクラスのオブジェクトへの参照を持つことができます。特にその変数は&tt(){ColoredPoint}への参照を持つことができます。 &i(){&small(){インタフェースのインスタンスは作成できず、作成できるのはクラスのインスタンスだけなので、&tt(){new Colorable()}というような式は無効です。しかし、式new Colorable() { public void setColor... }は有効です。これは&tt(){Colorable}インタフェースを実装した[[匿名クラス宣言>15.9.5. 匿名クラス宣言]]であるからです。}} }}}
*[[4. 型と値と変数]] **[[4.1. 型と変数の種類]] **[[4.2. プリミティブ型と値]] **[[4.3. 参照型と値]] **[[4.4. 型変数]] **[[4.5. 引数付き型]] **[[4.6. 型の抹消]] **[[4.7. 具象可能型]] **[[4.8. 未加工型]] **[[4.9. 交差型]] **[[4.10. サブタイプ化]] **[[4.11. 型の使用箇所]] **[[4.12. 変数]] ***[[4.12.1. プリミティブ型の変数]] ***[[4.12.2. 参照型の変数]] ***[[4.12.3. 変数の種類]] ***[[4.12.4. final変数]] ***[[4.12.5. 変数の初期値]] ***4.12.6. 型とクラスとインタフェース Javaプログラミング言語では、全ての変数や全ての式はコンパイル時に決定可能な型を持っています。型はプリミティブ型か参照型です。参照型にはクラス型やインタフェース型も含みます。参照型は[[クラス宣言>8.1. クラス宣言]]や[[インタフェース宣言>9.1. インタフェース宣言]]を含む型宣言によって導入されます。型という言葉をクラスやインタフェースを参照するのに用いることがしばしばあります。 Java仮想マシンでは、全てのオブジェクトはある特定のクラスに属しています。オブジェクトを生み出す[[作成式>15.9. クラスインスタンス作成式]]で書かれるクラスや、オブジェクトを生み出すのに&tt(){Class}オブジェクトのリフレクションメソッドが使用されるクラスや、[[文字列連結演算子+>15.18.1. 文字列連結演算子+]]で暗黙的に作成されるオブジェクトのための&tt(){String}クラスがあります。このクラスをオブジェクトのクラスと呼びます。オブジェクトはそのクラスのインスタンスであり、そのクラスの全てのスーパークラスのインスタンスです。 全ての配列もクラスに属しています。配列オブジェクトに対し&tt(){getClass}メソッドを呼び出すと配列のクラスを表す(&tt(){Class}クラスの)クラスオブジェクトを返します([[10.8.>10.8. 配列のためのClassオブジェクト]])。 変数のコンパイル時の型は常に宣言されており、式のコンパイル時の型はコンパイル時に決定可能です。コンパイル時の型は変数が実行時にとりうる値や式が実行時にとりうる値を制限します。実行時の値が&tt(){null}ではない参照ならば、あるクラスのオブジェクトや配列を参照しています。そのクラスはコンパイル時の型と必ず互換性があります。 変数や式はコンパイル時の型がインタフェースであるかもしれません。インタフェースのインスタンスはありません。インタフェース型の変数や式はそのインタフェースを実装するクラスのオブジェクトを参照します([[8.1.5.>8.1.5. スーパーインタフェース]])。 時々、変数や式は"実行時の型"を持ちます。これは実行時の変数や式の値を参照する値が&tt(){null}ではないオブジェクトのクラスを参照します。 コンパイル時の型と実行時の型の間の一致は2つの理由から不完全です。: 1. 実行時、クラスやインタフェースはJava仮想マシンによってクラスローダーを使いロードされます。どのクラスローダーもそれ自身のクラスやインタフェースを定義しています。結果として、2つのローダーが等価なクラスやインタフェース定義をロードすることが可能ですが、実行時には異なるクラスやインタフェースとなります。結果として、もしそれをロードするクラスローダーが一致しなければ、正しくコンパイルされたコードはリンク時に失敗するかもしれません。   &i(){&small(){詳しくは論文Dynamic Class Loading in the Java™ Virtual Machine、著者Sheng Liang、Gilad Bracha, Proceedings of OOPSLA '98、出版ACM SIGPLAN Notices、Volume 33、Number 10、1998年10月、ページ 36-44、およびThe Java™ Virtual Machine Specification, Java SE 7 Editionを参照してください。}} 2. [[型変数>4.4. 型変数]]と[[型実引数>4.5.1. 型実引数とワイルドカード]]は実行時に非具象可能です。結果として、実行時には同じクラスやインタフェースでもコンパイル時に複数の[[引数付き型>4.5. 引数付き型]]で表されることがあります。特に、与えられたジェネリック型宣言([[8.1.2.>8.1.2. ジェネリッククラスと型引数]]、[[9.1.2.>9.1.2. ジェネリックインタフェースと型引数]])のコンパイル時の呼び出しは全て単一の実行時の表現を共有します。   特定の状況下で、引数付き型の変数が引数付き型ではないオブジェクトを参照することが可能です。この状況は[[ヒープ汚染>4.12.2. 参照型の変数]]として知られています。変数は常に引数付き型を表すクラスのインスタンスであるオブジェクト参照します。 #divstyle(background-color:#f0f0ff;border:1px solid black;padding 4px){{{ &bold(){&aname(ex4.12.6-1,option=nolink){例4.12.6-1. 変数の型 対 オブジェクトのクラス}} interface Colorable { void setColor(byte r, byte g, byte b); } class Point { int x, y; } class ColoredPoint extends Point implements Colorable { byte r, g, b; public void setColor(byte rv, byte gv, byte bv) { r = rv; g = gv; b = bv; } } class Test { public static void main(String[] args) { Point p = new Point(); ColoredPoint cp = new ColoredPoint(); p = cp; Colorable c = cp; } } &i(){&small(){この例で:}} -&i(){&small(){&tt(){Test}クラスの&tt(){main}メソッドの局所変数&tt(){p}は&tt(){Point}型であり、初期値として&tt(){Point}クラスの新たなインスタンスを参照します。}} -&i(){&small(){同様に局所変数&tt(){cp}は&tt(){ColoredPoint}型であり、初期値として&tt(){ColoredPoint}クラスの新たなインスタンスを参照します。}} -&i(){&small(){変数&tt(){cp}の値を変数&tt(){p}に代入することで&tt(){p}は&tt(){ColoredPoint}オブジェクトへの参照を持ちます。これは&tt(){ColoredPoint}が&tt(){Point}のサブクラスのため許可されています。ゆえに&tt(){ColoredPoint}クラスは&tt(){Point}型と[[代入互換(assingment-compatible)>5.2. 代入変換]]です。&tt(){ColoredPoint}オブジェクトは&tt(){Point}の全てのメソッドをサポートしています。その特有のフィールド&tt(){r}、&tt(){g}、&tt(){b}に加えて、&tt(){Point}クラスのフィールド、すなわち&tt(){x}と&tt(){y}も持ちます。}} -&i(){&small(){局所変数&tt(){c}はインタフェース型&tt(){Colorable}です。変数は&tt(){Colorable}を実装するクラスのオブジェクトへの参照を持つことができます。特にその変数は&tt(){ColoredPoint}への参照を持つことができます。}} &i(){&small(){インタフェースのインスタンスは作成できず、作成できるのはクラスのインスタンスだけなので、&tt(){new Colorable()}というような式は無効です。しかし、式&tt(){new Colorable() { public void setColor... }}}}&i(){&small(){は有効です。これは&tt(){Colorable}インタフェースを実装した[[匿名クラス宣言>15.9.5. 匿名クラス宣言]]であるからです。}} }}}

表示オプション

横に並べて表示:
変化行の前後のみ表示:
目安箱バナー