(一):文字列関連

6973 ワード

public class StringTest {

    public static void main(String[] args) {
        String str = new String("abc"); // (1)
        String str1 = "abc";// (2)
        String str2 = new String("abc");// (3)
        
        System.out.println(str == str1);// (4)
        System.out.println(str == str2);// (5)
        System.out.println(str1 == str2);// (6)
        
        System.out.println(str == str.intern());// (7)
        System.out.println(str1 == str1.intern());// (8)
        System.out.println(str.intern() == str2.intern());// (9)
        
        String hello = "hello";// (10)
        String hel = "hel";// (11)
        String lo = "lo";// (12)
        
        System.out.println(hello == "hel" + "lo");// (13)
        System.out.println(hello == "hel" + lo);// (14)
	}
}

質問1:文(1)を実行したとき、メモリにいくつのオブジェクトが生成されますか?何ですか?どこですか.
解答:文(1)を実行すると、メモリにはabcという2つのオブジェクトが生成されます.strはオブジェクトではなく、オブジェクトのアドレスです.参照(reference)と呼ばれ、strはnewを指します.生成されたオブジェクト.つまりjavaでクラスの変数(String strなど)を定義するとオブジェクトではなく、常に参照されます.では、対象とは何でしょうか.キーワードnewを使用すると、生成されたものをオブジェクトと呼びます.どうして2人の相手なの?まず、オブジェクトがabcであることを生成します.このabcオブジェクトはどこにありますか.String Poolという文字列プールの中にあり、StringだけがこのようなStringプールを持っています.Stringプールはどんな概念ですか?Stringクラスは可変クラスであることは知っていますが、その内容が確定すると、変更することはできません.文字列オブジェクトを生成するとき、その実行プロセスはこうです.まず、tring str=new String(「abc」)がmainメソッドの最初の文であるため、実行を開始したばかりのとき、String Poolにはオブジェクトがありません.String Poolにabcというオブジェクトがないことを発見しました.では、まずnew String(「abc」)の括弧の中のabcオブジェクトをString Poolに入れ、次にnewを実行します.この行の文は、Stringの構築方法を実行します.newはオブジェクトを生成することを知っています.このオブジェクトはどこにありますか.Javaの山の中にあります.Javaのメモリは2つの部分に分かれており、1つはスタック(Stack)、1つはスタック(Heap)と呼ばれています.ではnew String(「abc」)では,スタック(Heap)の中にabcという内容のオブジェクトを生成する.これにより、String Poolの中にabcというオブジェクトがあり、スタックの中にもabcというオブジェクトがあります.ここではpublic String(String original)という構造方法を用いた.jdk apiはこう述べています.
Initializes a newly created String object so that is represents the same sequence of characters as the argument;in other words,the newly created string is a copy of the argument string.Unless an explicit copy of original is needed,use of this constructor is unnecessary since Strings are immutable.(翻訳:新しく作成されたStringオブジェクトを初期化し、パラメータと同じ文字列を表します.言い換えれば、新しく作成された文字列はパラメータ文字列のコピーです.Stringは可変ではないので、originalの明示的なコピーが必要でない限り、この構造方法を使用する必要はありません.)
質問2:文(2)を実行したとき、メモリには全部でいくつのオブジェクトがありますか?何ですか?どこですか.
解答:文(2)の実行が完了すると、メモリ内の新しいオブジェクトは生成されません.どうしてそう言うの?文(2)を定義するときに文字列の定数値(字面値)でstr 1に値を割り当てると、まずjavaがString Poolからabcという内容のオブジェクトが存在しないかを検索し、文(1)を実行したときにStringPoolにabcという内容のオブジェクトがすでに存在していることに気づき、tring Poolではabcという内容の文字列オブジェクトは生成されません.すでに存在するString Poolの中の内容がabcの文字列オブジェクトを使用し、str 2という参照をString Poolの中の内容がabcの文字列オブジェクトに指し、str 2はString Poolの中の内容がabcの文字列対像のアドレスを格納します.すなわち、String str 2=「abc」、すなわち文字列定数(「abc」)を使用して定義された参照(str 2)に値を割り当てると、まずString Poolの中にabcの内容の文字列オブジェクトが存在するかどうかを探し、ある場合は新しいオブジェクトを作成せずにString Poolの中にすでに存在するオブジェクトを直接参照します.ない場合は、String Poolで新しいオブジェクトを作成し、新しく作成したオブジェクトを参照します.したがって,文(2)の実行が完了するとメモリには2つのオブジェクトがあり,それらの内容はそれぞれabcであり,String Poolには1つのコンテンツabcのオブジェクトがあり,スタックには1つのコンテンツabcのオブジェクトがある.
質問3:文(3)を実行したとき、メモリには全部でいくつのオブジェクトがありますか?何ですか?どこですか.
解答:文(3)の実行が完了すると、まずString Poolでabcという文字列オブジェクトが存在するかどうかを検索し、そのオブジェクトが存在することを発見すると、新しいオブジェクトを作成しません.次にnew...、Javaにキーワードnewが存在する限り、それは新しいオブジェクトを生成することを示し、newは何度も、何個のオブジェクトを生成し、新しく生成されたオブジェクトはスタックの中にあるので、スタックの中にabcという内容のオブジェクトを生成し、str 2を参照str 2に割り当て、str 2はスタックの中で生成されたばかりの内容がabcのオブジェクトを指す.したがって、文(3)の実行が完了すると、メモリには3つのオブジェクトがあり、String Poolにはabcという文字列オブジェクトが含まれ、スタックにはabcという文字列オブジェクトが2つ含まれる.
質問4:文(4)(5)(6)を実行した後、それらの結果はそれぞれ何ですか.
回答:javaでは、オブジェクトを「==」で永遠に比較するのは2つのオブジェクトのメモリアドレスです.言い換えれば、「==」の左右の2つの参照が同じオブジェクトを指しているかどうかを比較します.Javaの中の8種類の原生データ型にとって、"=="はそれらの字面値が同じかどうかを比較します.アプリケーションタイプでは、メモリアドレスが同じかどうかを比較します.文(1)(2)(3)ではstr,str 1,str 2が異なるオブジェクトを指すためメモリアドレスが異なるため,文(4)(5)(6)の実行が完了するとfalseが返されるといえる.
質問5:文(7)(8)(9)を実行した後、それらの結果はそれぞれ何ですか.
jdk apiではメソッドpublic String intern()についてこう述べています.
Return a canonical representation for the string object.(翻訳:文字列オブジェクトの正規化された表示形式を返します.)A pool of strings,initially empty,is maintained privately by the class String.(翻訳:クラスStringによってプライベートに維持される最初は空の文字列プール.)When the intern method is invoked,if the pool already contains a string equeal to this String objectas determined by the equals(Object) method,then the string from the pool is returned.Otherwise,this String object is added to the pool and a reference to the String object is returned.(翻訳:internメソッドが呼び出されると、プールにこのStringオブジェクトに等しい文字列がすでに含まれている場合(オブジェクトはequals(Object)メソッドによって決定される)、プール内の文字列が返されます.そうでなければ、このStringオブジェクトをプールに追加し、このStringオブジェクトの参照を返します.)If follows that for any two strings s and t,s.intern() == t.intern() is true if and only if s.equals(t) is true.(翻訳:任意の2つの文字列sおよびtに従い、s.equals(t)がtrueである場合にのみ、s.intern()==t.intern()がtrueである.)All literal strings and string-valued consrant expressions are interned.String literals and defined in §3.10.5 of the Java Language Specification.(翻訳:すべてのフォント文字列と文字列付与定数式は内部的です.文字列フォント値は『Java Language Specification』の§3.10.5で定義されています.)Returns:a string that has the same contents as this string,but is guaranteed ro be from a pool of unique strings.(翻訳:文字列を返します.内容はこの文字列と同じですが、文字列プールから保証されます.)文(7)を実行すると、まずstrというオブジェクトはスタック内の最初のnewを指します.生成されたオブジェクトは、jdkのapiによると、internメソッドが呼び出されると、String PoolにこのStringオブジェクトに等しい文字列(equals(Object)メソッドによって決定される)がすでに含まれている場合、String Pool内の文字列オブジェクトのメモリアドレスが返される.String Poolにはabcの内容を持つオブジェクトがあるため、str.intern()はString Poolの内容がabcの文字列オブジェクトのメモリアドレス、すなわちstr 1を返す.一方、str=str 1はfalseであるため、str==str.intern()はfalse、すなわち文(7)の結果はfalseである.str 1についてはintern()は、まずString Poolにabcという内容のオブジェクトがあるかどうかをチェックし、あることを発見すると、String Poolにおけるabcという内容のオブジェクトのアドレスをstr 1に付与する.intern()メソッドの戻り値、すなわちstr 1.intern()の結果はstr 1であった.したがって、str 1==str 1.intern()の結果はtrue,すなわち文(8)の結果はtrueである.str.intern()では、まずString Poolにabcというオブジェクトがあるかどうかをチェックし、あることを発見すると、String Poolのabcというオブジェクトのstr.intern()メソッドに付与された戻り値、すなわちstr.intern()の結果がstr 1となる.st 2 rについてintern()は、まず、String Poolにabcという内容のオブジェクトがあるかどうかをチェックする、あることを発見すると、String Poolにおけるabcという内容のオブジェクトのアドレスをstr 2に付与する.intern()メソッドの戻り値、すなわちstr 2.intern()の結果はstr 1であった.したがって、str.intern()==str 2.intern()の結果はtrue,すなわち文(9)の結果はtrueである.したがって,文(7)(8)(9)の実行が完了すると,false,true,trueの結果となる.
質問6:文(13)(14)を実行した後、それらの結果はそれぞれ何ですか.
解答:実行済み文(13)はtrue、実行済み文(14)はfalseとなります.解析:hello=="hel"+"lo"に対して、helloはString Poolの中の内容がhelloの文字列オブジェクトを指し、"hel"+"lo"に対して、"+"の両方が文字列定数である場合、"+"を実行した後、String Poolの中にhelloの内容の文字列オブジェクトが存在するかどうかを判断し、ある場合はString Poolの中の内容がhelloの文字列オブジェクトのメモリアドレスに直接戻るので、hello==「hel」+「lo」の結果はtrueである.hello=="hel"+loに対して、loは字面値ではなく、"+"の両側に字面値ではない(文字列定数)がある場合、"+"操作後、スタック内に新しいオブジェクトが生成されます.つまり、helloの参照はString Poolの中の内容がhelloの文字列オブジェクトを指し、"hel"+loの結果はスタック内に新しいオブジェクトが生成され、1つはString Poolの中にあり、1つはスタックの中にあります.もちろんfalseです.