Java SE 7(Java 1.7)の Pointクラスの説明書(API)を改めて掲示しておきます→Pointクラス。
Pointクラスを利用する最もシンプルな例は、以下のような感じでした。
Point p = new Point();
このイメージは以下のような感じです。
結果的に、参照型変数 pを使用するだけで、int型の変数 x, yが利用できることになります。言い換えれば、2つの変数 x, yをひとまとめにして考えられる、ということでもあります。
なお、実際にはインスタンスフィールドの初期値は int型の場合には 0となるため、Point型インスタンスのインスタンスフィールド x, yにはそれぞれ 0が代入されています。
Point型インスタンスは、インスタンスフィールドを 2つ持っています。その名前は x と yです。ここではそれらを使用してみようと思います。Java SE 7(Java 1.7)の Pointクラスの説明書(API)を改めて掲示しておきます→Pointクラス。
Point型インスタンスをひとつ作成し、そのインスタンスフィールド x, yに対して、値を代入し、その値を確認するためのプログラムを書いてみます。
ソースコードは以下の通り。
H201/H201.java
import java.awt.Point; /** * Point型インスタンスを使用します。 */ public class H201 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { Point p = new Point(); // インスタンスフィールドへ値の代入 p.x = 10; p.y = 20; // インスタンスフィールドの参照 System.out.println("pの参照先インスタンスのインスタンスフィールド xの値は " + p.x); System.out.println("pの参照先インスタンスのインスタンスフィールド yの値は " + p.y); } }
実行結果は以下の通り。
pの参照先インスタンスのインスタンスフィールド xの値は 10 pの参照先インスタンスのインスタンスフィールド yの値は 20
このイメージは以下のような感じです。
ここで、p.x
のピリオド「.」の意味には注意が必要です。参照型変数の後ろについたピリオド「.」は、その参照型変数が指し示す先にあるインスタンスの…という意味です。したがって、p.x
は、「Point型の参照型変数 pが指し示す先にあるインスタンスが持つインスタンスフィールド x」という意味になります。
staticなメソッドや staticなフィールドのときにもピリオド「.」を使用しました。例えば、G102.factorial(~)
というように使用しましたが、このときのクラス名の後ろにつくピリオド「.」は、このクラスに所属するという意味になります。先ほどの例の場合には「G102クラスに所属する factorialメソッドを呼び出す」という意味でした。
ピリオド「.」の意味は 2種類あること、ピリオドの前に記述されているのがクラスなのか参照型変数なのかによって、まったく意味が変わることに十分注意してください。
続いて、複数のインスタンスを扱ってみます。インスタンスを 2つ作るためには予約語new
を 2回します。そして、両者を区別するために、参照型のローカル変数も 2つ用意します。
ソースコードは以下の通り。
H202/H202.java
import java.awt.Point; /** * Point型インスタンスを複数使用します。 */ public class H202 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { Point p = new Point(); Point q = new Point(); // pの参照先インスタンスのインスタンスフィールドへの値の代入 p.x = 30; p.y = 50; // qの参照先インスタンスのインスタンスフィールドへの値の代入 q.x = 100; q.y = 200; // インスタンスフィールドの参照 System.out.println("pの参照先インスタンスのインスタンスフィールド xの値は " + p.x); System.out.println("pの参照先インスタンスのインスタンスフィールド yの値は " + p.y); System.out.println("qの参照先インスタンスのインスタンスフィールド xの値は " + q.x); System.out.println("qの参照先インスタンスのインスタンスフィールド yの値は " + q.y); } }
実行結果は以下の通り。
pの参照先インスタンスのインスタンスフィールド xの値は 30 pの参照先インスタンスのインスタンスフィールド yの値は 50 qの参照先インスタンスのインスタンスフィールド xの値は 100 qの参照先インスタンスのインスタンスフィールド yの値は 200
このイメージは以下のような感じです。
参照型変数の参照先が nullの場合は、参照先インスタンスがありません。このとき、プログラムはどう動作するのでしょうか。実験してみます。
ソースコードは以下の通り。
H203/H203.java
(16行目に黄線が生じますが問題ありません)
import java.awt.Point; /** * 参照先がnullの場合の動きを確認します。 */ public class H203 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { Point p = null; // pの参照先インスタンスフィールドへの値の代入 p.x = 10; p.y = 20; } }
実行結果は以下の通り。
Exception in thread "main" java.lang.NullPointerException at H203.main(H203.java:16)
NullPointerExceptionの表示とともに強制終了しています。変数 pの参照先にインスタンスは存在しないのですから、インスタンスフィールド x や yにアクセスできるはずがありません。そういう訳で、強制終了となってしまいました。なお、NullPointerExceptionは、オブジェクト指向に慣れるまでには最も遭遇する確率の高い例外(Exception)になります。とりあえず言葉を覚えておくと良いかと思います。
なお、強制終了の詳細や例外(Exception)およびエラーについては、しばらく後の章「例外」にて解説します。
Point型インスタンスは、インスタンスメソッドを幾つか持っています。Pointクラスで宣言されているメソッドは、equals, getLocation, getX, geetY, move, setLocation, setLocation, setLocation, toStrong, translateの 10種類であることが確認できます。詳細は、Java SE 7(Java 1.7)の Pointクラスの説明書(API)を改めて掲示しておきます→Pointクラス。
また、継承の関係によって、上記の 10種類のインスタンスメソッド以外にも幾つかのインスタンスメソッドが使用できますが、詳細については後の章の解説によって理解できるようになると思います。
インスタンスメソッドである translateを利用することにします。translateメソッドの説明文を引用すると次の通り。
public void translate(int dx, int dy) (x,y) の位置にあるこの点を、x 軸に沿って dx、y 軸に沿って dy に移動して、点 (x+dx,y+dy) を表すようにします。 パラメータ: dx - X 軸に沿ってこの点が移動する距離 dy - Y 軸に沿ってこの点が移動する距離
さっそく、このメソッドを使用したプログラムを製作してみましょう。
ソースコードは以下の通り。
H204/H204.java
import java.awt.Point; /** * インスタンスメソッド translateを使用します。 */ public class H204 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { Point p = new Point(); // インスタンスフィールドに値を代入する p.x = 10; p.y = 20; // インスタンスメソッドを使用する p.translate(40, -5); // インスタンスフィールドの値を表示する System.out.println("pの参照先インスタンスのインスタンスフィールド xは " + p.x); System.out.println("pの参照先インスタンスのインスタンスフィールド yは " + p.y); } }
実行結果は以下の通り。
pの参照先インスタンスのインスタンスフィールド xは 50 pの参照先インスタンスのインスタンスフィールド yは 15
インスタンスフィールド xの値は 10→50に、yの値は 20→15に変化したことが分かります。
インスタンスメソッドの使用の仕方は、参照型変数の後ろにピリオドを使用して、その後ろにメソッド名を記述してきます。参照型変数の後ろについたピリオド「.」は、インスタンスフィールドのときと同様、その参照型変数が指し示す先にあるインスタンスの…という意味です。したがって、p.translate(~)
は、「Point型の参照型変数 pが指し示す先にあるインスタンスが持つインスタンスメソッド translateを、指定した引数にて呼び出す」という意味になります。
このイメージは以下のような感じです。
Point型インスタンスを含む、すべてのインスタンスには toStringメソッドが存在します。toStringメソッドが具体的にどんな内容を表示するかは、型によってまちまちなのですが、基本的にはそのインスタンスの状態を表す文字列を表示します。Pointクラスの説明書(API)には以下のように記述されています。
public String toString() この点および (x,y) 座標空間でのこの点の位置を表す文字列を返します。
このメソッドはデバッグ専用であり、返される文字列の内容および形式は実装によって異なります。
返される文字列は空の場合がありますが、null にはなりません。 オーバーライド: クラス Object 内の toString 戻り値: この点の文字列表現
この記述の通り、デバッグ(テスト)の際に使用すると便利なときがあります。さっそく、利用してみます。
ソースコードは以下の通り。
H205/H205.java
import java.awt.Point; /** * toStringメソッドを使用します。 */ public class H205 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { Point p = new Point(); // インスタンスフィールドに値を代入する p.x = 10; p.y = 20; // インスタンスを文字列として表示する System.out.println(p.toString()); // 暗黙的な toStringメソッドの呼び出し System.out.println("pの参照先インスタンスの中身は " + p); } }
実行結果の例は以下の通り(実行環境によって出力結果が異なることがあります)。
java.awt.Point[x=10,y=20] pの参照先インスタンスの中身は java.awt.Point[x=10,y=20]
23行目に注目してください。ただ pと書いただけでも、toStringメソッドの出力結果と同じになっています。これは、文字列に対して参照型変数を「+」で連結した場合、自動的に.toString()
が追加されるためです。言い換えれば、この場合には.toString()
が省略されている、ということでもあります。これは Point型の変数に限らず、すべての参照型変数で同様の動作をします。
Pointクラスは、コンストラクタを 3種類持っています。Java SE 7(Java 1.7)の Pointクラスの説明書(API)を改めて掲示しておきます→Pointクラス。
ここまでのサンプルでは、引数なしのコンストラクタのみを利用してきました。ここでは、2種類のコンストラクタを利用してみることにします。
ソースコードは以下の通り。
H206/H206.java
import java.awt.Point; /** * 複数のコンストラクタを使用します。 */ public class H206 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { Point p = new Point(); Point q = new Point(100, 200); // インスタンスの内容を表示する System.out.println("変数 pの参照先インスタンスの内容は " + p); System.out.println("変数 qの参照先インスタンスの内容は " + q); } }
実行結果の例は以下の通り(実行環境によって出力結果が異なることがあります)。
変数 pの参照先インスタンスの内容は java.awt.Point[x=0,y=0] 変数 qの参照先インスタンスの内容は java.awt.Point[x=100,y=200]
このソースコードではインスタンスを 2つ生成しています。一方は、引数なしのコンストラクタを利用してインスタンスを生成しています。もう一方は、2つの int型を引数とするコンストラクタを利用してインスタンスを生成しています。
このように引数ありのコンストラクタを利用することで、初期化を手短かに記述することができることがあります。
また、クラスによっては引数無しのコンストラクタが存在せず、何らかの引数を設定しなければならないこともあります。他にも、利用できるコンストラクタが存在しないために、インスタンスを生成することができないクラスもあります(例えば、Systemクラスや Mathクラス)が、それについては後の章で解説します。