Java String作成オブジェクトインスタンス解析


本論文で研究したのは主にJava String作成対象の問題です。
まず、二つの概念を理解したいです。変数とオブジェクトを参照してください。オブジェクトは主にnewによってヒープ内に作成されます。Stringは参照変数だけです。
すべての文字列はStringオブジェクトです。文字列の定数が多く使われているため、javaでは時間を節約するために、コンパイル段階では、文字列の定数を文字列の常数池に置いています。文字列の定数プールは同じ文字列を結合して空間を占用できるという利点があります。
Javaでは変数のアドレスを直接取得できませんが、2つの参照変数が1つのアドレスであるオブジェクトを指しているかどうかを判定します。
スタックメモリ
メモリ
ベースタイプ、オブジェクト参照(ヒープメモリアドレス)
newで作成されたオブジェクトと配列
アクセス速度が速い
スタックメモリに対して遅い
データのサイズは宣言の周期で決めなければなりません。
割り当てられたメモリはJava仮想マシンの自動ゴミ回収器によって管理される。メモリサイズを動的に割り当てる
共有特性は、スタックに文字列がある場合、直接参照します。ない場合は、新しいスペースの預け入れ値を開きます。
new毎にメモリに新しいオブジェクトを生成します。多重化は存在しません。

package com.demo.test;

import java.lang.reflect.Field;

public class StringDemo {

  public static void main(String[] args) {
    //                   ,              ;
    String str1 = "abc";
    String str2 = "abc";
    /*
     public String toString() {
      return this;
     }
     */
    String str3 = "abc".toString();
    //                  ,        。
    String str4 = new String("abc");
    String str5 = new String("abc");
    String str6 = str5;
    String str7 = "a" + "b" + "c";
    String str8 = "a" + "b" + new String("c");
    //String         ,StringBuilder StringBuffer        (            ),StringBuffer    ,StringBuilder     
    String str9 = new StringBuilder().append("a").append("b").append("c").toString();
    String str10 = new StringBuffer().append("a").append("b").append("c").toString();

    System.out.println("--------> ==");
    System.out.println("---> 1");
    System.out.println(str1==str2);//true

    System.out.println("---> 3");
    System.out.println(str3==str1);//true

    System.out.println("---> 4");
    System.out.println(str4==str1);//false
    System.out.println(str4==str3);//false
    System.out.println(str4==str5);//false
    System.out.println(str4==str6);//false

    System.out.println("---> 7");
    System.out.println(str7==str1);//true
    System.out.println(str7==str3);//true
    System.out.println(str7==str4);//false

    System.out.println("---> 8");
    System.out.println(str8==str1);//false
    System.out.println(str8==str3);//false
    System.out.println(str8==str4);//false
    System.out.println(str8==str7);//false

    System.out.println("---> 9");
    System.out.println(str9==str1);//false
    System.out.println(str9==str3);//false
    System.out.println(str9==str4);//false
    System.out.println(str9==str7);//false
    System.out.println(str9==str8);//false

    System.out.println("---> 10");
    System.out.println(str10==str1);//false
    System.out.println(str10==str3);//false
    System.out.println(str10==str4);//false
    System.out.println(str10==str7);//false
    System.out.println(str10==str8);//false
    System.out.println(str10==str9);//false

    System.out.println("--------> equals");
    System.out.println(str1.equals(str4));//true
    System.out.println(str1.equals(str7));//true
    System.out.println(str1.equals(str8));//true

    System.out.println("--------> hashCode");
    /*
     hashCode    : s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
        hashCode     ,          
     */
    System.out.println(str1.hashCode());//96354
    System.out.println(str2.hashCode());
    System.out.println(str3.hashCode());
    System.out.println(str4.hashCode());
    System.out.println(str5.hashCode());
    System.out.println(str6.hashCode());
    System.out.println(str7.hashCode());

    System.out.println("--------> normal change value");
    //String     ,string           ,            ,      , string                 
    str6 = "123";
    System.out.println(str5);//abc
    System.out.println(str6);//123

    System.out.println("--------> reflect change value");
    /*
           String  ,      。       。
     public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
       // The value is used for character storage.
       private final char value[];
       ……
     }
    */
    str6 = str5;
    try {
      Field field = String.class.getDeclaredField("value");
//     Field field = str6.getClass().getDeclaredField("value");
      if(!field.isAccessible()) {
        field.setAccessible(true);
      }
      char[] value = (char[])field.get(str6);
      value[0] = '0';
      System.out.println(str5);//0bc
      System.out.println(str6);//0bc
    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
      e.printStackTrace();
    }

    System.out.println("--------> obj.toString()");
    Object obj = new Object();
    /*
    public String toString() {
      return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    */
    System.out.println(obj.toString());//java.lang.Object@15db9742

    String[] arr1 = {"0"};
    String[] arr2 = {"0"};
    System.out.println(arr1.equals(arr2));//false
  }
}
締め括りをつける
  • もしStringが文字列定数を指しているなら、まず文字列定数プール(スタック)で検索し、あれば直接にそれを指す。ない場合は、文字列定数プールで定数を作成し、Stringはその定数を指します。
  • Stringがキーワードnewを使用して初期化すると、スタック内に固定空間を開けて文字列の値を格納し、Stringがその定数を指す。
  • は文字列定数を使用して、表式は右値を先に計算するので、Stringを新しいスティッチングされた文字列定数に向けるのに相当します。文字列の定数セルで検索します。あれば直接に指します。ない場合は、文字列定数プールで定数を作成し、Stringはその定数を指します。ただし、つなぎ合わせの中にnewを使って生成された文字列があると、新しい文字列はnewを使ってスタックの中で作成されたものと同じである。
  • により、Stringの値が変更され、Stringの指向だけが変更され、Stringのオブジェクト自体は変更されない。オブジェクト自体を変更する必要がある場合は、反射を使用することができます。
  • は、配列である場合、オブジェクトであるため、equalsは配列ポインタアドレスだけを比較し、それらの要素が等しいかどうかを比較しない。
  • 以上がJava String作成対象事例解析のすべての内容です。皆様の助けをお願いします。興味のある方は引き続き当駅の他のテーマを参照してください。友達のサポートに感謝します。