ホームページ  >  記事  >  Java  >  Java の String オブジェクト データ型の包括的な分析

Java の String オブジェクト データ型の包括的な分析

高洛峰
高洛峰オリジナル
2017-01-19 14:35:271509ブラウズ

1. まず、String は 8 つの基本データ型に属しません。

オブジェクトのデフォルト値は null であるため、String のデフォルト値も null ですが、これは特別なオブジェクトであり、他のオブジェクトにはないいくつかの特性があります。

2. new String() と new String("") は両方とも、空の文字列であり、null ではありません。

String str=new String ( "kvill"); の違い:
ここでは、ヒープやスタックについては説明せず、最初に定数プールの単純な概念を簡単に紹介します。
定数プールとは、コンパイル時に決定され、コンパイル済みプールに保存されるプールを指します。クラスファイル内の一部のデータ。これには、文字列定数だけでなく、クラス、メソッド、インターフェイスなどの定数も含まれます。

例 1 を見てください:

String s0="kvill"; 
String s1="kvill"; 
String s2="kv" + "ill"; 
System.out.println( s0==s1 ); 
System.out.println( s0==s2 );

結果は次のとおりです:

true

true
まず第一に、結果として Java は文字列定数のコピーが 1 つだけ存在することを保証することになることを知っておく必要があります。
例の s0 と s1 の "kvill" は両方とも文字列定数であり、コンパイル時に決定されるため、文字列の場合は s0==s1 が true となり、"kv" と "ill" も文字列定数になります。が複数の文字列定数で連結されている場合、それ自体が文字列定数でなければならないため、s2 もコンパイル時に文字列定数に解析されるため、s2 は定数プール A 引用符内でも「kvill」になります。
したがって、s0==s1==s2 を取得します
new String() で作成された文字列は定数ではなく、コンパイル時に決定できないため、new String() で作成された文字列は定数プールには入れられません。独自のアドレス空間を持っています。
例 2 を見てください:

String s0="kvill"; 
String s1=new String("kvill"); 
String s2="kv" + new String("ill"); 
System.out.println( s0==s1 ); 
System.out.println( s0==s2 ); 
System.out.println( s1==s2 );

結果は次のとおりです:

false

false
false
例 2 では、s0 は依然として定数プール内の "kvill" の適用です。s1 はコンパイル時に決定できないため、実行時に作成される新しいオブジェクト "kvill" を参照すると、s2 には newString("ill") の後半があるため、コンパイル時に決定できません。したがって、新しく作成されたオブジェクト "kvill" のアプリケーションでもあります。これを理解すれば、なぜこの結果が得られるのかがわかるでしょう。

4. String.intern():

もう 1 つ追加させてください: に存在します。クラス ファイル内の定数プールは、実行時に JVM によってロードされ、拡張できます。 String の intern() メソッドは、定数プールを拡張するメソッドです。String インスタンス str が intern() メソッドを呼び出すと、Java は定数プール内に同じ Unicode を持つ文字列定数があるかどうかを確認し、存在する場合は返します。そうでない場合は、定数プールに str に等しい Unicode 文字列を追加し、その参照を返します。例 3 を見ると明らかです。例 3:

String s0= "kvill"; 
String s1=new String("kvill"); 
String s2=new String("kvill"); 
System.out.println( s0==s1 ); 
System.out.println( "**********" ); 
s1.intern(); 
s2=s2.intern(); //把常量池中"kvill"的引用赋给s2 
System.out.println( s0==s1); 
System.out.println( s0==s1.intern() ); 
System.out.println( s0==s2 );

結果は次のようになります:
false

**** ********

false //s1.intern() は実行されますが、その戻り値は s1 に代入されません
true //s1.intern() が定数の "kvill" への参照を返すことを示しますプール
本当
最後にそれを壊します 間違った理解:
誰かが「String.intern() メソッドを使用して、String クラスをグローバル String テーブルに保存します。同じ値を持つ Unicode 文字列がすでにこのテーブルに存在する場合、 、このメソッドは、テーブル内に同じ値を持つ文字列が存在しない場合は、テーブルに独自のアドレスを登録します。彼が言及したグローバル String テーブルが定数であると理解すれば、このメソッドは返します。 pool, his last 一文で言えば、「テーブルに同じ値の文字列がなければ、自分のアドレスをテーブルに登録する」は間違いです:
例 4 を見てください:

String s1=new String("kvill"); 
String s2=s1.intern(); 
System.out.println( s1==s1.intern() ); 
System.out.println( s1+" "+s2 ); 
System.out.println( s2==s1.intern() );

结果为: 
false 
kvill kvill 
true 
在这个类中我们没有声名一个"kvill"常量,所以常量池中一开始是没有"kvill"的,当我们调用s1.intern()后就在常量池中新添加了一个"kvill"常量,原来的不在常量池中的"kvill"仍然存在,也就不是"将自己的地址注册到常量池中"了。 
s1==s1.intern()为false说明原来的"kvill"仍然存在; 
s2现在为常量池中"kvill"的地址,所以有s2==s1.intern()为true. 

5. 关于equals()和==: 

这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。 

6. 关于String是不可变的 

这一说又要说很多,大家只要知道String的实例一旦生成就不会再改变了,比如说:String str="kv"+"ill"+" "+"ans"; 
就是有4个字符串常量,首先"kv"和"ill"生成了"kvill"存在内存中,然后"kvill"又和" " 生成 "kvill "存在内存中,最后又和生成了"kvill ans";并把这个字符串的地址赋给了str,就是因为String的"不可变"产生了很多临时变量,这也就是为什么建议用StringBuffer的原因了,因为StringBuffer是可改变的。

更多Java中的String对象数据类型全面解析相关文章请关注PHP中文网!

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。