回答編集履歴
1
回答を追記
answer
CHANGED
@@ -3,4 +3,53 @@
|
|
3
3
|
- Flyweightデザインパターン
|
4
4
|
- コンスタントプール
|
5
5
|
- Stringプール
|
6
|
-
- String.intern()
|
6
|
+
- String.intern()
|
7
|
+
|
8
|
+
###回答(追記)
|
9
|
+
『擬似プリミティヴ型』は『Java言語仕様』にも『Java仮想マシン仕様』にも定義されていません。私はこの言葉に何の意味も見出せません。質問に回答すべきではなかったと思いますが、擬似的な解説のようなものを書いてみます。
|
10
|
+
|
11
|
+
>「擬似プリミティブ型」なるものがどのようなものかを知りたいのです。
|
12
|
+
|
13
|
+
これはご自分で結論を書かれています。Du sagt.
|
14
|
+
|
15
|
+
>「擬似プリミティブ型」の定義、文字列リテラルとはどのような関係なのか、そういった点です。
|
16
|
+
|
17
|
+
文字列リテラルと全く同じではない。他の回答者のswordoneさんが触れている『文字列プール』に格納された文字列(あるいは文字列の参照)だと解釈することができます。別の言い方をすると”intern”された文字列です。「文字列リテラルとは定数式のことで、唯一のインスタンスを共有するよう”intern”されたものである。」(下手な翻訳)
|
18
|
+
|
19
|
+
###String.intern(追記)
|
20
|
+
以下は蛇足ですが、実験コードを書きます。
|
21
|
+
文字列リテラルを先に『文字列プール」に格納して後から、同じ文字列のインスタンスをヒープに作成してinternする。
|
22
|
+
|
23
|
+
```Java
|
24
|
+
String a = "abcd";
|
25
|
+
System.out.println(System.identityHashCode(a));
|
26
|
+
|
27
|
+
String b = new String(new char[]{'a','b','c','d'});
|
28
|
+
System.out.println(System.identityHashCode(b));
|
29
|
+
|
30
|
+
b = b.intern();
|
31
|
+
System.out.println(System.identityHashCode(b));
|
32
|
+
```
|
33
|
+
バイトコードは、aに文字列リテラルを代入するのは putfield、bに代入する文字列をnewするのはinvokespecial、internするのはinvokevirtualです。
|
34
|
+
|
35
|
+
文字列リテラルより先に、文字列をヒープにインスタンス化してinternしてみる。
|
36
|
+
|
37
|
+
```Java
|
38
|
+
String c = new String(new char[]{'e','f','g','h'});
|
39
|
+
System.out.println(System.identityHashCode(c));
|
40
|
+
|
41
|
+
c = c.intern();
|
42
|
+
System.out.println(System.identityHashCode(c));
|
43
|
+
|
44
|
+
String d = "efgh";
|
45
|
+
System.out.println(System.identityHashCode(d));
|
46
|
+
```
|
47
|
+
|
48
|
+
先に登録したものが使われることがわかります。
|
49
|
+
最後に、言うまでもないことですが、文字列プールに格納された文字列は、次のことが成り立ちます。
|
50
|
+
|
51
|
+
a == b ならば a.equals(b) // 言語仕様のとおり
|
52
|
+
a.equals(b) ならば a == b // Flyweight型の文字列
|
53
|
+
|
54
|
+
ラッパークラスのvalueOfが事前に用意されたインスタンスを返すことについては省略します。
|
55
|
+
なぜ言語仕様にString.internが書かれなければならなかったのか、こちらの方が気になります。
|