5

com.sun.org.apache.xerces.internal.impl.XMLScannerのソースコードの 183行目と18 ​​6行目

183    protected final static String fVersionSymbol = "version".intern();

186    protected final static String fEncodingSymbol = "encoding".intern();

「バージョン」「エンコーディング」が文字列リテラルであり、自動的にインターンされるのに、intern()を使用して明示的にインターンされるのはなぜですか?

4

2 に答える 2

6

Apache Xerces SVNリポジトリでリビジョン318617への変更を追跡しました(これは、パッケージ名が示すように、このXMLパーサーが最初に開発されたプロジェクトです)。

コミットメッセージの関連部分は次のとおりです。

シンボルテーブルの使用を改善しようとしています。パーサーがリセットされるたびに、多くの事前定義された文字列がシンボルテーブルに追加されます。小さなドキュメントの場合、これはかなりのコストになります。シンボルテーブルの文字列に対してString#internを呼び出すので、これらの事前定義されたシンボルに対してString#internを使用するだけで十分です。これは一度だけ実行する必要があります。

お気づきのように、準拠しているJVM実装では、は.intern()必要ではありません(そして目に見える影響はありません)。

私の推測では

  • どちらの作者も、文字列リテラルが常にインターンされるという事実に気づいていませんでした
  • または、JVMの実装の誤動作を防ぐための意識的な決定でした

ただし、2番目のケースでは、コメントまたはコメントメッセージにそのメモが含まれていると思います。

.intern()この呼び出しの副作用の1つは、初期化子が定数式ではなくなり、フィールドがそれらを参照する他のクラスによってインライン化されないことです。これにより、クラスXMLScannerがロードされ、そのフィールドが読み取られます。ただし、これはここでは関係ないと思います。

于 2012-11-02T14:24:15.287 に答える
4

あなたが特定した理由から、その理由はないと思います。クラスで定義されているStringように、リテラルは常に自動的にインターンされます。

すべてのリテラル文字列と文字列値の定数式がインターンされます。文字列リテラルは、Java™言語仕様のセクション3.10.5で定義されています。

于 2012-11-02T14:14:45.947 に答える