復習(オブジェクト)


Java言語ではオブジェクトは基本的には「new クラス名(引数)」というコンス トラクタの呼び出しによってのみ作られる。例外としては、文字列定数や配列 の初期化がある。
class T{
  public static void main(String[] args){
    int table[]={1,2,3,1,2};
//              ^^^^^^^^^^^ これが配列の初期化          
    System.out.println("Hello World");
//                     ^^^^^^^^^^^^^ これが文字列定数
  }
}
 オブジェクトはヒープ領域というところに置かれる。変数はローカル変数(メ ソッド内の変数)、インスタンス変数、クラス変数等によって置かれる場所が違 うが、オブジェクト型の変数はオブジェクトへの参照だけを持つ小さい(1ワー ドの)箱となっている。

例として、

class Point{
  int x,y;
  public Point(int xx, int yy){ x=xx; y=yy; }
}
で、
Point p1=new Point(1,2);
とした時の絵を下に示す。
代入や引数渡しをする際はオブジェクトを新たに作って渡すのではなく、オブジェクトへの 参照をそのまま渡す。従って、下のように p1をp2に代入してからp2.xを書き換えると、 p1.xも書き変わっている。
// オブジェクトの生成
Point p1=new Point(1,2);
// 代入ではオブジェクトを新たに生成せず
// 参照のみコピーしたので、p2とp1は同じところを指すようになる
Point p2=p1;
// p2を書き換え
p2.x=3;
// 1ではなく3が表示される
System.out.println(p1.x);
引数渡しをする場合も同様である。
class T1{
  // pのxを返すがついでにp.xを1増やす
  static int getXandIncrement(Point p){
    int x=p.x;
    p.x++;
    return x;
  }
  public static void main(String args[]){
    Point p1=new Point (1,3);
    // 1を表示する
    System.out.println(getXandIncrement(p1));
    // 2を表示する
    System.out.println(p1.x);
  }
}
このことを考えると、演算子 == がオブジェクトの同一性を表すという意味が分かってく るかもしれない。
class Point {
    int x,y;
    public Point(int xx,int yy){
	this.x=xx; this.y=yy;
    }
    //    public boolean equals(Point p){
    //	return x==p.x && y==p.y;
    //    }
}
class t{
    public static void main(String[] args){
	Point p1=new Point(0,1);
	Point p2=new Point(0,1);
        // == は同一性を表すので falseになる
	System.out.println(p1==p2);
        // == は同一性を表すので trueになる
	System.out.println(p1==p1);
        // == は同一性を表すので trueになる
	System.out.println(p2==p2);
        // Point クラスで equalsが定義していない時は == と同じ
	System.out.println(p1.equals(p1));
        // equalsは同値性を表すように定義するので true にしたいが、
	System.out.println(p1.equals(p2));
    }
}
上の例でPointのequalsは未定義だが、Java言語のすべてのクラスは java.lang.Object という名前のクラスのサブクラスとなっていて、その中で equalsは
class Object {
  ....
  public boolean equals(Object o){
    return this==o;
  }
}
のように定義されているため、そのようになっている。
ここで、述べたオブジェクトと参照の関係は多くのオブジェクト指向言語でも 通用する議論だが、世の中でよく使われる C++ という言語では成り立たない。 C++では代入やメソッドへの引数渡しなどいたるところで、オブジェクトが作ら れる。

C++では演算子のオーバーライドという機能が用意されていて、この機能を利用して 演算子 == は同一性を表すのではなく、同値性を表すように定義されているのが普 通である。

なお、すべてのクラスがObjectクラスのサブクラスであることを利用した便利 な機能がある。作成したクラスに
String toString();
という名前のメソッドを定義しておくと、
class Point {
    int x,y;
    public Point(int xx,int yy){
	this.x=xx; this.y=yy;
    }
    //    public boolean equals(Point p){
    //	return x==p.x && y==p.y;
    //    }
    public String toString(){
	return "Point("+x+","+y+")";
    }
}
class t2{
    public static void main(String[] args){
	Point p1=new Point(0,1);
	System.out.println(p1);
    }
}
のように、暗黙の文字列への変換が適用されて、プログラムの動作を確かめる際に便利である。
次に進む