Javaの文字列に関する質問を考えてみましょう。「ABC " + '/'と「ABC」 +"/"の違いです。この例を介して、JDKツールでJavapの使用を練習できます。元の質問は次のとおりです。
スラッシュ/キャラクターまたは文字列としての扱いの違いは何ですか?
1つは基本的なデータ型Charとして使用され、もう1つはオブジェクト文字列です。特定の違いは何ですか?
キャラクターとして扱う方が効率的ですか?
string str = "abc" + '/';
そして
string str = "abc" + "/";
1。コンパイラの最適化
まず第一に、上記の2つの文が上記の2つの文を次のように最適化するため、上記の2つの文が同じ効果があることを知っておく必要があります。
string str = "abc/";
Javapを通じてこれを証明できます。 Javapについては、「すべてのJava開発者が知っておくべき5つのJDKツール」を参照できます。最初にクラスを作成します:StringOne、およびメインメソッドの次のコードを入力します。
stringone.javastring str1 = "abc" + '/'; string str2 = "abc" + ";" /"; system.out.println(str1 == str2);
コンパイルして実行すると、出力の結果は真です。次に、Javapが起動します。コマンドラインに次のコマンドを入力します。
javap -v -l stringone.class> stringone.s
次に、生成されたStringone.sファイルを確認します。あなたはそれにいくつかの線があることがわかります
Stringone.s#2 = String#20 // ABC /.....# 20 = UTF8 ABC/... 0:LDC#2 // STRING ABC/2:Store_13:LDC#2 // String ABC/5:Store_2
説明:STR1とSTR2は両方とも文字列「ABC/」を参照しています。
2。javapを使用して違いを分析します
それでは、質問を変更しましょう。次のコードのStringAddStringとStringDcharメソッドの違いは何ですか?
StringTwopupic String String StringDString(String Str1、String Str2){return str1 + str2;} public static string stringdchar(string str、char ch){return str + ch;}今回、Javapは逆コンパイルに使用され、生成されたファイルの内容の一部は次のとおりです。
stringtwo.spublic java.lang.string stringaddstring(java.lang.string、java.lang.string);記述子:( ljava/lang/string; ljava/lang/string;)ljava/lang/string;フラグ:acc_publicコード:stack = 2、locals = 3、args_size = 3 0:new#2 // class java/lang/stringbuilder 3:dup 4:invokespecial#3 // method java/stringbuilder。追加:(ljava/lang/string;)ljava/lang/stringbuilder; 11:ALOAD_2 12:InvokeVirtual#4 //方法Java/Lang/StringBuilder。追加:(ljava/lang/string;)ljava/lang/stringbuilder; 15:InvokeVirtual#5 //方法Java/Lang/StringBuilder。 toString :()ljava/lang/string; 18:areturnpublic java.lang.string stringaddchar(java.lang.string、char);記述子:( ljava/lang/string; c)ljava/lang/string;フラグ:acc_public code:stack = 2、locals = 3、args_size = 3 0:new#2 // class java/lang/stringbuilder 3:dup 4:invokespecial#3 // method java/lang/stringbuilder。 Java/Lang/StringBuilder.Append :( ljava/lang/string;)ljava/lang/stringbuilder; 11:ILOAD_2 12:InvokeVirtual#6 // Method Java/Lang/StringBuilder.Append:(c)Ljava/Lang/StringBuilder; 15:InvokeVirtual#5 // Method Java/Lang/StringBuilder.ToString :()Ljava/Lang/String; 18:areturn
これで、これら2つの方法を実行するプロセスをはっきりと見ることができます。
StringAddString
StringAddCharの手順はStringAddStringと同じです。ただし、Appendメソッドが2回目と呼ばれる場合、StringDStringのパラメーターは文字列型であり、StringAddCharのパラメーターはcharタイプです。
3。StringBuilderクラスの追加(char)メソッドと追加(文字列)メソッド
ここでは、ソースコードを直接確認する必要があります(鉱山はJDK1.8.0_60に付属のソースコードです)。ドキュメントは、StringBuilderがオブジェクトからソースコードから継承することを示していますが、抽象クラスの抽象的なストリングビルダーから継承されていることに注意してください。 AppendメソッドはAbstractStringBuilderによって実装されます。
AbstractStringBuilder.java
public AbstractStringBuilder Append(Char C){ensureCapacityInternal(count + 1); //アレイがカウント+1文字の値に対応できることを確認します[count ++] = c;これを返します;} public AbstractStringBuilder append(string str){if(str == null)return appendnull(); int len = str.length(); ensurecapacityinternal(count + len); str.getchars(0、len、value、count); //文字列内の文字配列をこのオブジェクトcount += lenの文字配列にコピーします。これを返します;}残りはもう投稿されません。 string.getchars(int、int、char []、int)は、最終的にはpublic staticネイティブのvoid arraycopy(object、int、object、int、int)に依存します。言い換えれば、それはC言語で記述される可能性があり、Javaで書かれたプログラムよりも大きなアレイをコピーする場合、効率はより良いはずです。それで、今、私が理解していることを教えてください:
直接メモリに関しては、文字列にはchar配列が含まれているため、配列には長さフィールドが必要です。同時に、文字列クラスにはintハッシュプロパティもあり、オブジェクト自体は他の情報を保存するために追加のメモリを占有するため、文字列はより多くのメモリを占有します。ただし、文字列が非常に長い場合、これらのメモリオーバーヘッドはほとんど無視できます。また、文字列が(非常に)短い場合、これらのメモリオーバーヘッドを共有するための多くの共有参照があるため、余分なメモリオーバーヘッドはまだ無視できます。
コールスタックから、文字列にはここでのcharよりも1つまたは2つの関数呼び出しのみがあるため、関数呼び出しのオーバーヘッド(時間と空間を含む)が考慮されない場合、類似する必要があります。関数呼び出しのオーバーヘッドが考慮される場合、「ABC」 + '/'の方が良いはずです。しかし、複数の文字を接続する必要がある場合(この状況はより一般的であるべきだと思いますよね?)、Charは接続を完了するために多くのループを必要とするため、呼ばれる関数の数は文字列を使用するよりも呼び出されます。同時に、コピーは文字列がアレイを直接コピーするよりも高速ではありません。したがって、この時点で、より大きなスループットで「ABC」 + "/"になります。
今、私はこの質問が尋ねているように感じます:ファイルを読み書きするときにシステム呼び出しを使用する方が効率的ですか、または標準の関数ライブラリでIOライブラリを使用する方が効率的ですか。個人的には、標準のIOライブラリは最終的にシステムコールを呼び出し、いくつかの一時的な変数とより深いコールスタックが生成されると感じています。同様に、文字列クラスにはより多くのフィールドとより深い関数スタックがありますが、キャッシュとより直接的なコピーのためにスループットの方が良いはずです。
新しい質問
上記のJavap逆コンパイルコードから判断すると、2つの文字列が一緒に加えられると、StringBuilderの文字列が追加されます。それでは、理論的には、次のコードのどれがより効率的ですか?
string str1 = "abc" + "123"; // 1StringBuilder StringBuilder = new StringBuilder(); // 2StringBuilder.Append( "ABC"); StringBuilder.Append( "123"); string str2 = stringbuilder.tostring();
誰もが考えるためにこの質問を残してください!
上記はこの記事のすべてのコンテンツであり、Javaの文字列+文字列と文字列+charをよりよく区別するのに役立ちます。みんなの学習に役立つことを願っています。