java.util.RandomAccessインタフェースの目的

Javaクイズです。java.util.RandomAccessというインタフェースにはメソッドが1つも宣言されていません。メソッドが1つも宣言されていないインタフェースが何の役に立つのでしょうか。

定数インターフェイス。( Effective Java でやるなって書いてたナア…。)


API を見てみる。
Iterator より高速且つ簡単に要素にアクセス出来る。ほう…。
というかよく分からないので RandomAccess.class を見てみる。


package java.util;
public interface RandomAccess {
}
これだけ…?


検索してみたらありました。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=4406&forum=12&7

このうち、RandomAccessを実装しているものは
ArrayList, Vector の2つだけです。

ソースを見てみると ArrayListVector は RandomAccess を implements してるが、 LinkedList はしてない。

hyukiさんから頂いた問題

hyuki 『以下もどうぞ。
String s = "abc";
System.out.println(s == s.replace('a', 'a'));
System.out.println(s == new String(s));
System.out.println(s == new String("abc").intern());』 (2005/12/29 22:08)

結果


true
false
true
s == new String(s) が false を返すのは同一のオブジェクトでは無いから。
System.out.println(s.equals(new String(s)));
なら同じ文字列なので true を返す。


s == s.replace('a', 'a')
replaceメソッドの説明を読むと一見 false が返ってきそうな気がする。

public String replace(char oldChar,char newChar)
この文字列内にあるすべての oldChar を newChar に置換した結果生成される、新しい文字列を返します。

新しい文字列であって新しいオブジェクトではないので true が返る。


s == new String("abc").intern()
さて、問題はこれですね。新しく String オブジェクト作ってるから false が返ってきそうなのに true が返ってる。

public String intern()
文字列オブジェクトの正準表現を返します。
文字列のプールは、初期状態では空で、クラス String によってプライベートに保持されます。

intern メソッドが呼び出されたときに、equals(Object) メソッドによってこの String オブジェクトに等しいと判定される文字列がプールにすでにあった場合は、プール内の該当する文字列が返されます。そうでない場合は、この String オブジェクトがプールに追加され、この String オブジェクトへの参照が返されます。

このため、任意の 2 つの文字列 s と t においては、s.equals(t) が true の場合にのみ、s.intern() == t.intern() は true になります。

新しい String オブジェクトを生成する。
String regex = new String("abc");
s.equals(regex) は true なので s.intern() == regex.intern() も true になる。


hyukiさん、ありがとうございます。

不変性を選ぶ

前回の続き

分からない時は javadoc を見てみる。

文字列は定数です。この値を作成したあとに変更はできません。文字列バッファは可変文字列をサポートします。文字列オブジェクトは不変であるため、共用することができます。

不変 - Effective Java の項目13を見てみよう。
Effective Java p.61 項目13 不変性を選ぶ
更に分からなくなってくる。というかあんまり関係無かった…。

たとえば BigInteger クラスは、内部的には「符号 - 大きさ」表現を使用しています。

すると"String クラスは、内部的には「char 型の配列 - 長さ」表現を使用しています"?
String クラスを見てみるとそれっぽい感じになってますね。それっぽいという事にしておきましょう。


char[] str = {'a','b','c'};
System.out.println(str1.equals(str));

false が返ってくるのは基本データ型と参照型を比較してるから。


String str1 = "abc";

StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");

System.out.println(sb.toString().equals(str1));

上のコードでは true が返る。


String string = new String(str);
System.out.println(str.toString());
System.out.println(string.toString());

str.toString() はメモリのアドレスを返す。string.toString() は値。


public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

toString() メソッド - Object クラス
Effective Java p.40 項目9 toString を常にオーバーライドする

(略)その文字列は、クラス名、「アットマーク(@)」、ハッシュコードの符号なし16進数表現から構成されており、(後略)

次回は「ハッシュコードとナポリタンの謎を追え!」です。お楽しみに。

String型

以下の3つのjava.lang.String型のオブジェクトがあるとき、
trueを表示するコードをすべて選択してください。

String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");

A.  System.out.println(str1 == str2);
B.  System.out.println(str1 == str3);
C.  System.out.println(str1.equals(str2));
D.  System.out.println(str2.equals(str3));

==はオブジェクトが同一かどうか。equalsメソッドは値が同じかどうか。
Aは同じオブジェクトなのでtrue
Bはオブジェクトが違うからfalse
Cは文字列が同じなのでtrue
Dも文字列が同じなのでtrue

実行してみる


true
false
true
true
合ってた…。

char型の配列を使ってみる
char[] str = {'a','b','c'};
System.out.println(str1.equals(str));

実行結果


false
何故?
あとで考えよう。あとでやろう。あとでよもう。あとで

Javaのアクセス修飾子

Javaのアクセス修飾子(外部からのアクセスレベルを制御するキーワード)をすべて答えなさい。

public
protected
なし
private

またclassに付加することができるアクセス修飾子をすべて答えなさい。

あれ?上のがこっちかな?