せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Java】リテラル・参照・文字列オブジェクト パーフェクトJava学習感想文 その2

パーフェクトJavaを読んで改めてJavaを振り返り中。

息も絶え絶えです。

経緯については学習記録その1をご参照ください。

以下、学んだこと。

 

Stringオブジェクトと文字列リテラル

文字列リテラルはStringオブジェクト = Stringクラスのインスタンス
言い換えると、文字列リテラルはString型の振る舞いを持つということ。

System.out.println("hoge".charAt(2)); ←g
System.out.println(1.getClass()); ←コンパイルエラー

 

Java プログラム内の「abc」などのリテラル文字列はすべて、このクラスのインスタンスとして実行されます。

http://docs.oracle.com/javase/jp/6/api/java/lang/String.html#String(java.lang.String)

リテラル表記できることと基本型であることは全く別の概念。
イコールではない。


文字列リテラル自体がオブジェクトなので、
一般的なString変数宣言↓は、変数を参照しているだけ

String a = "hoge";

 
言い換えたら、こういうイメージ

String a = b;

"hoge"オブジェクトのポイントする先をaも参照しているだけ。


 

文字列の内容は不変

例えば

String a = "hog" + "e";

とした場合、aはコンパイル時に新しく作成された"hoge"オブジェクトを参照する。
よって、元の"hog"オブジェクトや"e"オブジェクトは変更されない。
(=オペランドの変数の状態が変わらないので +演算子を使った式は副作用がない、と言える)
 
Javaの仕様にも載っている↓

15.17.1 文字列連結演算子 +
一つのオペランドの式だけが型Stringならば,実行時に文字列を生成するために,他方のオペランドに対して文字列変換を実行する。結果は二つのオペランドの文字列を連結して新たに作成したオブジェクト String への参照とする。

http://www.y-adagio.com/public/standards/tr_javalang/15.doc.htm#39990

ちなみに

 s += "hoge"

とした場合は、内部的にStringBuilderオブジェクトが生成される。

文字列連結は StringBuilder (または StringBuffer) クラスとその append メソッドを使って実装されています。

http://docs.oracle.com/javase/jp/6/api/java/lang/String.html#String(java.lang.String)


基本型変数は、「値そのもの」が入っている

変数に数値を代入することで、数値を名前つきで扱うことができます。

確かに。なるほど。
変数に「そのものが入っている」(=参照ではない)と理解することで、
下の内容も良く分かる。

 

ドット演算子の演算対象は「参照値」

演算対象は「変数」ではない。
 

new Car().toString();  ←OK
"hoge".length();  ←OK
1.length(); ←「参照」してないからNG
int i = 99;
i.length(); ←NG。iは参照ではなく値が代入されている変数だから。


 
以上、
リテラル・参照・文字列オブジェクトについて、でした。