Java String で intern メソッドを使用する方法
定数プールの概要
JAVA 言語には 8 つの基本型と特殊な型 String があります。実行を高速化し、より多くのメモリを節約するために、これらの型には定数プールの概念が (メソッド領域に) 提供されています。定数プールは、JAVA システム レベルで提供されるキャッシュに似ています。 8 つの基本タイプの定数プールはすべてシステムによって調整されますが、文字列タイプの定数プールは特別です。
文字列定数プールを使用するには、主に 2 つの方法があります。
二重引用符を使用して直接宣言された文字列オブジェクトは、定数プールに直接保存されます。
String オブジェクトが二重引用符で宣言されていない場合は、String によって提供される intern メソッドを使用して、それを定数プールに入れることができます。
Intern メソッドの紹介 (JDK7)
プロトタイプ: publicネイティブ String intern();
説明:
文字列定数プールから現在の文字をクエリします。文字列が存在するかどうか (等しいかどうかで判断)。
存在する場合は、定数プール内の文字列参照を返します。
存在しない場合は、String オブジェクト参照を定数プールに保存し、String オブジェクト参照を返します。
戻り値: すべては、String 変数に対応する文字列定数プールへの参照を返します。
例
package com.example; public class Demo { public static void main(String argv[]) { String s = "test"; System.out.println(s == s.intern()); } }
JDK6以前: falseを出力
JDK7以降: trueを出力
原則(JDK6およびJDK7)
定数プール内の文字列の起源
JDK6 以前の String.intern() を呼び出す
定数に文字列がある場合プールにある場合、定数が返されます。 プール内のこの文字列への参照
定数プールに参照がない場合は、オブジェクトのコピーをコピーして、定数プールに置きます。 (永続的な世代); 戻り値は、定数プール (永続的な世代) 内の対応する文字列インスタンスへの参照です。
JDK7 以降は String.intern() を呼び出します。
定数プールに文字列がある場合は、その文字列への参照を返します。 constant pool
定数プールがない場合は、参照をコピーして定数プール (ヒープ) に置きます (JDK1.7 では String 定数プールを Perm 領域からJava ヒープ領域)
ルーチン テスト
ルーチン 1:
package org.example.a; public class Demo { public static void main(String argv[]) { String s1 = new String("1"); s1.intern(); String s2 = "1"; System.out.println(s1 == s2); String s3 = new String("1") + new String("1"); s3.intern(); String s4 = "11"; System.out.println(s3 == s4); } }
結果
jdk6: false false
jdk7: false true
jdk8:false true
ルーチン 2:
package org.example.a; public class Demo { public static void main(String argv[]) { String s1 = new String("1"); s1.intern(); String s2 = "1"; System.out.println(s1 == s2); String s3 = new String("1") + new String("1"); String s4 = "11"; s3.intern(); System.out.println(s3 == s4); } }
上記のコードの 2 番目の部分にスワップがあります。
結果
jdk6:false false
jdk7:false false
jdk8:false false
ルーチン分析
下の図では、緑色の線は String オブジェクトを指すコンテンツを表します。赤い線はアドレスを示しています。
jdk1.6
ルーチン 1 とルーチン 2 の分析
上図に示すように。まず jdk6 の状況について説明します. jdk6 では、定数プールが Perm 領域に配置され、Perm 領域が通常の JAVA ヒープ領域から完全に分離されているため、上記の出力はすべて false になります。前述したように、文字列が引用符を使用して宣言されている場合、その文字列は文字列定数プールに直接生成され、新しい String オブジェクトは JAVA ヒープ領域に配置されます。したがって、JAVA Heap領域のオブジェクトアドレスと文字列定数プールのオブジェクトアドレスを比較すると明らかに異なり、String.internメソッドを呼び出しても関係がありません。
jdk1.7
Jdk6 以前のバージョンでは、文字列の定数プールはヒープの Perm 領域に配置されます。Perm 領域は、主に静的領域に格納されます。クラス情報、定数プール、メソッドフラグメントなどのデフォルトのサイズはわずか 4m ですが、定数プールで大量のインターンが使用されると、java.lang.OutOfMemoryError:PermGen スペース エラーが発生します。 jdk7 バージョンでは、文字列定数プールが Perm 領域から通常の Java ヒープ領域に移動されました。移動が必要な主な理由は、Perm エリアが小さすぎるためですが、もちろん、ニュースによると、jdk8 は Perm エリアを直接キャンセルし、新しいメタ エリアを確立しました。 JDK 開発者は、Perm 領域が現在の JAVA 開発にはもはや適していないと考えているはずです。文字列定数プールが JAVA ヒープ領域に移動されましたが、なぜ上記のような結果が出力されるのか説明してください。
ルーチン 1 の分析
##1.String s1 = new String("1");
分析: このコード行は 2 つのオブジェクト (定数プールの「1」と JavaHeap の文字列オブジェクト) を生成します。 s.intern(); この文は、s1 オブジェクトが定数プールに検索に行き、「1」がすでに定数プールにあることが判明したことを意味します。 このとき、s1 は Java ヒープ内の文字列オブジェクトを指します。2.String s2 = "1";
分析: このコード行は、定数プール内の「1」オブジェクトを指す s2 への参照を生成します。その結果、s1 と s2 の参照アドレスが異なります。3.String s3 = 新しい文字列("1") 新しい文字列("1");
分析:这行代码生成了2个对象(字符串常量池中的“1” 和 Java Heap中的 s3 引用指向的对象“11”(中间还有2个匿名的new String("1")我们不讨论它)。
此时s3 是Java Heap中的字符串对象的引用,对象内容是”11″,此时常量池中是没有 “11”对象的。
4.s3.intern();
分析:这行代码将 s3中的"11"字符串放入String 常量池中,因为此时常量池中不存在"11"字符串,因此常规做法是跟 jdk6 图中表示的那样,在常量池中生成一个"11"的对象,关键点是 jdk7 中常量池不在Perm区域,而是在堆中了。常量池中不需再存储一份对象了,可以直接存储堆中的引用。这份引用指向s3引用的对象。 也就是说引用地址是相同的。
此时,s3是Java Heap中的字符串对象的引用,对象内容是”11″,此时常量池中是有 “11”对象,它保存的就是s3引用地址。
5.String s4 = "11";
这行代码”11″是显式声明的,因此会直接去常量池中创建,创建时发现已经有这个对象了。
此时:s4 == 常量池的“11”对象引用 == s3引用对象的引用
例程2的分析
String s1 = new String("1");
s1.intern();
String s2 = "1";
分析:s1.intern();,这一句往后放也不会有什么影响了,因为对象池中在执行第一句代码String s = new String("1");的时候已经生成“1”对象了。下边的s2声明都是直接从常量池中取地址引用的。 s1 和 s2 的引用地址是不会相等的。
String s3 = new String("1") + new String("1");
分析:这行代码生成了2个对象(字符串常量池中的“1” 和 Java Heap中的 s3 引用指向的对象“11”(中间还有2个匿名的new String("1")我们不讨论它)。
此时s3 是Java Heap中的字符串对象的引用,对象内容是”11″,此时常量池中是没有 “11”对象的。
String s4 = "11";
分析:声明 s4 的时候常量池中是不存在“11”对象的,执行完后,s4是常量池里“11“对象的引用。
s3.intern();
分析:此时常量池中“11”对象已经存在了,不会有任何操作,s3仍然是堆中String对象的引用。因此 s3 != s4
应用实例
package org.example.a; import java.util.Random; public class Demo { static final int MAX = 1000 * 10000; static final String[] arr = new String[MAX]; public static void main(String argv[]) { Integer[] DB_DATA = new Integer[10]; Random random = new Random(10 * 10000); for(int i = 0; i < DB_DATA.length; i++){ DB_DATA[i] = random.nextInt(); } long t = System.currentTimeMillis(); for(int i = 0; i < MAX; i++){ //arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length])); arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length])).intern(); } System.out.println((System.currentTimeMillis() -t) + "ms"); System.gc(); } }
上述代码是一个演示代码,其中有两条语句不一样,一条是使用 intern,一条是未使用 intern。
运行的参数是:-Xmx2g -Xms2g -Xmn1500M
不用intern
2160ms
使用intern
826ms
通过上述结果,我们发现不使用 intern 的代码生成了1000w 个字符串,占用了大约640m 空间。 使用了 intern 的代码生成了1345个字符串,占用总空间 133k 左右。其实通过观察程序中只是用到了10个字符串,所以准确计算后应该是正好相差100w 倍。虽然例子有些极端,但确实能准确反应出 intern 使用后产生的巨大空间节省。
细心的同学会发现使用了 intern 方法后时间上有了一些增长。这是因为程序中每次都是用了 new String 后, 然后又进行 intern 操作的耗时时间,这一点如果在内存空间充足的情况下确实是无法避免的,但我们平时使用时,内存空间肯定不是无限大的,不使用 intern占用空间导致 jvm 垃圾回收的时间是要远远大于这点时间的。 毕竟这里使用了1000w次intern 才多出来1秒钟多的时间。
以上がJava String で intern メソッドを使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHPは、シンプルな構文と高い実行効率を備えたWeb開発に適しています。 2。Pythonは、簡潔な構文とリッチライブラリを備えたデータサイエンスと機械学習に適しています。

PHPは、サーバー側で広く使用されているスクリプト言語で、特にWeb開発に適しています。 1.PHPは、HTMLを埋め込み、HTTP要求と応答を処理し、さまざまなデータベースをサポートできます。 2.PHPは、ダイナミックWebコンテンツ、プロセスフォームデータ、アクセスデータベースなどを生成するために使用され、強力なコミュニティサポートとオープンソースリソースを備えています。 3。PHPは解釈された言語であり、実行プロセスには語彙分析、文法分析、編集、実行が含まれます。 4.PHPは、ユーザー登録システムなどの高度なアプリケーションについてMySQLと組み合わせることができます。 5。PHPをデバッグするときは、error_reporting()やvar_dump()などの関数を使用できます。 6. PHPコードを最適化して、キャッシュメカニズムを使用し、データベースクエリを最適化し、組み込み関数を使用します。 7

PHPは、特に迅速な開発や動的なコンテンツの処理に適していますが、データサイエンスとエンタープライズレベルのアプリケーションには良くありません。 Pythonと比較して、PHPはWeb開発においてより多くの利点がありますが、データサイエンスの分野ではPythonほど良くありません。 Javaと比較して、PHPはエンタープライズレベルのアプリケーションでより悪化しますが、Web開発により柔軟性があります。 JavaScriptと比較して、PHPはバックエンド開発により簡潔ですが、フロントエンド開発のJavaScriptほど良くありません。

PHPとPythonにはそれぞれ独自の利点があり、さまざまなシナリオに適しています。 1.PHPはWeb開発に適しており、組み込みのWebサーバーとRich Functionライブラリを提供します。 2。Pythonは、簡潔な構文と強力な標準ライブラリを備えたデータサイエンスと機械学習に適しています。選択するときは、プロジェクトの要件に基づいて決定する必要があります。

phphassiblasifly-impactedwebdevevermentandsbeyondit.1)itpowersmajorplatformslikewordpratsandexcelsindatabase interactions.2)php'sadaptableability allowsitale forlargeapplicationsusingframeworkslikelavel.3)

PHPが多くのWebサイトよりも優先テクノロジースタックである理由には、その使いやすさ、強力なコミュニティサポート、広範な使用が含まれます。 1)初心者に適した学習と使用が簡単です。 2)巨大な開発者コミュニティと豊富なリソースを持っています。 3)WordPress、Drupal、その他のプラットフォームで広く使用されています。 4)Webサーバーとしっかりと統合して、開発の展開を簡素化します。

PHPはWeb開発およびコンテンツ管理システムに適しており、Pythonはデータサイエンス、機械学習、自動化スクリプトに適しています。 1.PHPは、高速でスケーラブルなWebサイトとアプリケーションの構築においてうまく機能し、WordPressなどのCMSで一般的に使用されます。 2。Pythonは、NumpyやTensorflowなどの豊富なライブラリを使用して、データサイエンスと機械学習の分野で驚くほどパフォーマンスを発揮しています。

H5開発で習得する必要があるツールとフレームワークには、Vue.JS、React、Webpackが含まれます。 1.Vue.jsは、ユーザーインターフェイスの構築に適しており、コンポーネント開発をサポートします。 2.複雑なアプリケーションに適した仮想DOMを介したページレンダリングを最適化します。 3.Webpackは、モジュールのパッケージングに使用され、リソースの読み込みを最適化します。
