JAvaメモリ割当て定数プール

4912 ワード

classファイルでは、定数プールが最も複雑で注目すべき内容です.Javaは動的接続言語であり、定数プールの役割は非常に重要であり、定数プールには、コードで定義された様々な基本タイプ(int、longなど)とオブジェクトタイプ(Stringや配列など)の定数値のほか、クラスやインタフェースの全制限名など、テキスト形式で表示されるシンボル参照も含まれています.フィールドの名前と記述子;メソッドと名前と記述子.C言語では、あるプログラムが他のライブラリの関数を呼び出す場合、接続時にその関数のライブラリ内の位置(すなわち、ライブラリファイルの先頭に対するオフセット量)がプログラムに書き込まれ、実行時に直接このアドレスに行って関数を呼び出す.Java言語ではそうではなく、すべてが動的です.コンパイル時に、他のクラスメソッドの呼び出しや他のクラスフィールドへの参照が見つかった場合、classファイルに記録されるのは、1つのテキスト形式のシンボル参照のみであり、接続中に仮想マシンはこのテキスト情報に基づいて対応するメソッドまたはフィールドを検索します.したがって、Java言語のいわゆる「定数」とは異なり、classファイルの「定数」の内容は非常に豊富ではありません.これらの定数はclassの1つの領域に集中して保存され、1つはすぐ1つで、ここでは「定数プール」と呼ばれます.
回転:http://hi.baidu.com/rickmeteor/blog/item/f0be11dff578ba1662279848.html
JAvaの定数プールテクノロジーは、特定のオブジェクトを簡単に作成するために登場し、オブジェクトが必要な場合にプールから1つを取り出すことができ(プールにない場合は1つを作成)、等しい変数を繰り返し作成する必要がある場合に多くの時間を節約します.定数プールは、newキーを使用して作成されたオブジェクトが存在するスタックスペースとは異なるメモリスペースです.本文はjava使用者の角度からjava定数プール技術を検討するだけで、定数プールの原理と実現方法には関与しない.個人的には、本当にjavaに集中しているなら、これらの詳細について一定の理解が必要だと思います.しかし、その原理と具体的な実現方法を知ることは必要ではない.
1,定数プール内のオブジェクトとスタック内のオブジェクト
public class Test{
   Integer i1=new Integer(1);
   Integer i2=new Integer(1);
<span style="white-space:pre">	</span>//i1,i2             
   System.out.println(i1==i2);//  false

   Integer i3=1;
   Integer i4=1;
//i3,i4             

   System.out.println(i3==i4);//  true
//   ,i1,i3         
   System.out.println(i1==i3);//  false

}

2,8種類の基本タイプのパッケージクラスとオブジェクトプール
JAvaの基本タイプの包装クラスの大部分は定数プール技術を実現しており、これらのクラスはByte,Short,Integer,Long,Character,Booleanであり、他の2種類の浮動小数点数タイプの包装クラスは実現していない.また、Byte、Short、Integer、Long、Characterの5種類のパッケージクラスも、対応する値が127以下の場合にのみ使用できます.つまり、オブジェクトは127以上のオブジェクトの作成と管理を担当しません.以下に、対応するテストコードを示します.
public class Test{

public static void main(String[] args){

   //5       Byte,Short,Integer,Long,Character   ,

   //    127        

   Integer i1=127;

   Integer i2=127;

   System.out.println(i1==i2)//  true

   //   127 ,          

   Integer i3=128;

   Integer i4=128;

   System.out.println(i3==i4)//  false

   //Boolean          

   Boolean bool1=true;

   Boolean bool2=true;

   System.out.println(bool1==bool2);//  true

   //                 

   Double d1=1.0;

   Double d2=1.0;

   System.out.println(d1==d2)//  false
   }
}

3,Stringも定数プール技術を実現
Stringクラスもjavaで多く使われているクラスであり、同様にStringオブジェクトの作成の便利さのために定数プールの技術も実現しており、テストコードは以下の通りである.
public class Test{

<span style="white-space:pre">	</span>public static void main(String[] args){

<span style="white-space:pre">		</span>//s1,s2          

<span style="white-space:pre">		</span>String s1=new String("hello");

<span style="white-space:pre">		</span>String s2=new String("hello");

<span style="white-space:pre">		</span>System.out.println(s1==s2)//  false

<span style="white-space:pre">		</span>//s3,s4        

<span style="white-space:pre">		</span>String s3="hello";

<span style="white-space:pre">		</span>String s4="hello";

<span style="white-space:pre">		</span>System.out.println(s3==s4);//  true

<span style="white-space:pre">	</span>}
}

最後:
細部が成否を決め、コードを書くのはなおさらだ.
Integerオブジェクトの補足:http://hi.baidu.com/fandywang_jlu/blog/item/c5590b4eae053cc3d1c86a13.html
Integerのパッケージでしょう:
   
public static Integer valueOf(int i) {
         final int offset = 128;
         if (i >= -128 && i <= 127) { // must cache
            return IntegerCache.cache[i + offset];
         }
          return new Integer(i);
       }

Integerオブジェクトにint値を直接与えると、valueOfメソッドが呼び出され、128の値が割り当てられます.cacheメソッドは行われず、newの2つの新しいオブジェクトに相当します.したがって、問題でa、bを定義する2つのコードは、次のようなものです.
      Integer a = new Integer(128);
      Integer b = new Integer(128); この時にまた聞きますが、出力結果は何ですか?falseだと知っていますこの数を127に変えて実行すると、
      Integer a = 127;
      Integer b = 127;
      System.out.println(a == b); 結果は:true
以上から,オブジェクト比較を行う際にはequalsを用いることが望ましく,自分の目的に応じて制御しやすいことが分かる.
---------------------------------------------------------------------------------------------------------------------------
IntegerCacheというクラスの内容を見てみましょう.
private static class IntegerCache {
      private IntegerCache() {
      }
      static final Integer cache[] = new Integer[-(-128) + 127 + 1];
      static {
         for (int i = 0; i < cache.length; i++)
            cache[i] = new Integer(i - 128);
      }
   }

Cache[]はIntegerCacheクラスで静的配列であるため,一度だけ初期化する必要がある,すなわちstatic{…}部分的には、Integerオブジェクトの初期化時に-128~127の範囲であれば、申請スペースを再定義する必要はなく、同じオブジェクトであるIntegerCacheである.Cacheでは,これによりある程度効率を向上させることができる.