2009-12-02 6 views
34

私はこのようなレガシーコードの多くを参照してください。ときインターンを使用する()

class A { 
    public static final String CONSTANT = "value".intern(); 
    ... 
} 

私は1つを読むことができるのJavadocのように、)(インターンのために何らかの理由が表示されません。 "すべてのリテラル文字列と文字列定数定数式は使用できません。"この言語の過去の改訂版には、これが何らかの意図がありますか?

+7

pjp以外の人が実際にこの質問を読んで回答しましたか? – Adamski

+0

[すべてのコンパイル時の定数はインライン化されていますか?](http://stackoverflow.com/questions/377819/are-all-compile-time-constants-inlined) –

答えて

65

これはCONSTANTが実際に一定でないことを保証する技術です。

Javaコンパイラは最終的な静的プリミティブまたは文字列への参照を参照すると、その定数の実際の値を使用しているクラスに挿入します。その後、定義クラスの定数値を変更するが、使用クラスを再コンパイルしないと、古い値が引き続き使用されます。

"定数"文字列でintern()を呼び出すと、もはやコンパイラによる静的定数とみなされないため、使用するクラスは実際に使用するたびに定義クラスのメンバにアクセスします。


JLSの引用:コンパイル時定数の

+4

これは私がトリックと呼ぶものです – pjp

+1

私はこれを実験的に確認しましたが、JLSの引用がありますか? –

+0

これはhttp://stackoverflow.com/questions/377819/are-all-compile-time-constants-inlinedに似ています – pjp

16

定数文字列リテラルにintern()を使用すると、3.10.5. String LiteralsThe Java® Language Specificationで指定されているように、リテラルがすでにインメモリーされているため、時間の無駄です。 Java SE 8版から引用

はまた、文字列リテラルは常にクラスStringの同じインスタンスを指します。これは、文字列リテラルまたはより一般的には、定数式(15.28)の値である文字列が、String.internメソッドを使用して一意のインスタンスを共有するために「インターナショナル」になっているためです。

私はコーダーがこの事実に感謝しなかったと思います。

編集:kdgregoryとして

は、この定数をインライン化することができるどのように影響があると指摘しています。

1からhttps://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5

+3

JLSはアウトカムについて語りますが、明確ではありませんこの折り畳みがコンパイル時に起こるかどうか、あるいは実行時にコンパイル時のフォールディングとconcatenate-and-then-internの間に目に見える違いがなくてはならないかどうかということです。バイトコード検査は、2つの文字列連結リテラルがクラスファイル内で1つになるかどうかを判断します。 – seh

5

私はintern()ed all o fクラスファイルから来る文字列(クラスファイルパーサー用)。 Intern()はプログラムのメモリ使用量を減らしましたが(他の人が指摘しているようにはなりません)、プログラムが大幅に遅くなりました(rt.jarをすべて解析するのに4秒かかったと思います。 8秒以上)。それを調べると(JDK 1.4だったと思いますが)、intern()コードはかなり醜いですし、遅くなる可能性があります。

私のコードでintern()を呼び出すことを考えた場合、私はまずintern()を使わずにプロファイルを作成し、次にintern()でメモリとスピードの両方をプロファイリングし、どちらが悪いのかを調べます。

+2

うわー...と正確な情報のためのダウン投票は何のためだった?情報が間違っていますか? – TofuBeer

+0

確かにpjpはこの質問の下降声でかなり寛大であった –

+2

私は下の票を気にしない...ちょうど彼らの理由:-) – TofuBeer

0

"locked"にintern()を使用しました。たとえば、私は "貿易記録"の "リポジトリ"を持っているとしましょう。私は貿易を編集し更新しているが、貿易をロックしたい。 tradeId.intern()をロックして、貿易のクローンが浮かんでいることを心配する必要がないようにすることができます。みんながこの使い方を気に入っているかどうかはわかりません。

これは、idフィールドが誤って別のドメインオブジェクトのidフィールドと衝突しそうにないことを前提として - tradeIdは1つがまた

synchronized(account.getAccountNumber().intern()) {...} 

をやっているかもしれない場所、例えばACCOUNT_NUMBERと衝突して発生しません。 example

+0

スカラのSymbolsは基本的にString.intern()をやっていませんか? –

関連する問題