私はJavaでこのような何かを行うことができます知っています:
String foo = 'a' + "bee";
私は印刷する場合はfoo
、コンソールに私が取得したいですabee
。何がここで実際にカバーの下に起こっているのでしょうか?私は仮定'a'
に推進されているString
が、私はこの種類の変換を支配するもののルールはよく分かりません。これは、ラッパークラスにプリミティブ型からマップをオートボクシングとして、私の知る限りオートボクシングのケースのように思われない(例えばint
- > Integer
)。されるString
のラッパーと考えますかchar
?
このもう少し面白くすることの一つは、私が何かをすれば似ていることである String test = 'a' + 'b';
私は、コンパイルエラーが発生します。私は、彼らは追加しているとき、私のような何かを得るだろうと予想するのが妥当と思われるものの文字は、整数として扱われるため、これがあることを理解"ab"
してtest
追加する際の挙動を与えられたchar
としますString
。
あなたは正確に使用している理由という名前の+
文字列の連結のために、オペレータは、歴史的な設計ミスと見ることができます。組み込みの連結演算子を提供することは間違っていないですが、それはプラス演算子ではなかったはずです。
異なる行動についての混乱に加えて、例えばのために'a'+'b'
と""+'a'+'b'
、プラス演算子は、通常可換であることが予想され、つまりはa + b
同じ結果を持っているb + a
文字列の連結のために保持しません。さらに、演算子の優先順位は驚きにつながることができます。
動作がされ、正確に(JLS§15.18.1)指定します:
15.18.1。文字列連結演算子+
唯一のオペランド式のタイプである場合
String
、文字列変換(§5.1.11は)実行時に文字列を生成するために他のオペランドに対して行われます。文字列連結の結果への参照である
String
2つのオペランド列の連結であるオブジェクト。左側の文字オペランドは右のオペランド新しく作成された文字列の文字の前に。
この定義は、にリンク§5.1.11:
5.1.11。文字列の変換
任意のタイプの型に変換することができる
String
ことにより、文字列変換。値が
x
プリミティブ型のは、T
第一の基準値に変換されるような場合に適切なクラスインスタンス生成式(引数としてそれを与えることによって15.9)。
場合
T
でboolean
、その後、使用new Boolean(x)
。場合
T
でchar
、その後、使用new Character(x)
。場合
T
であるbyte
、short
またはint
、その後使用new Integer(x)
。場合
T
でlong
、その後、使用new Long(x)
。場合
T
でfloat
、その後、使用new Float(x)
。場合
T
でdouble
、その後、使用new Double(x)
。この基準値は、型に変換された
String
文字列変換によって。今だけ基準値を考慮する必要があります。
参照がある場合
null
、それは文字列「に変換されnull
、」(4つのASCII文字n
、u
、l
、l
)。そうでなければ、変換は、の呼び出しによってかのように実行される
toString
引数なしで参照されたオブジェクトの方法。呼び出しの結果場合にはtoString
方法がありnull
、その後、文字列は「null
」代わりに使用されます。
(スペックの真の書式設定する「であるnull
というよりも」"null"
)
だから、のふるまいをString foo = 'a' + "bee";
すること指定されて、もしあなたが書きましたString foo = new Character('a').toString() + "bee";
しかし§15.18.1引用し続けて:
String
オブジェクトが新たに(作成され§12.5式が定数式(ある場合を除く)15.28)。実装が作成した後、中間廃棄を回避するために、1つのステップで変換及び連結を行うことを選択することができる
String
オブジェクト。繰り返される文字列連結のパフォーマンスを向上させるために、Javaコンパイラを使用することができるStringBuffer
中間体の数低減するクラスまたは類似の技術をString
、式の評価によって作成されたオブジェクトを。プリミティブ型の場合、実装はまた、文字列にプリミティブ型に直接変換することによって、ラッパー・オブジェクトの作成を離れて最適化することができます。
だからあなたの具体的な例について、'a' + "bee"
の、実際の行動
String foo = 'a' + "bee";
なります
String foo = "abee";
実行時に任意の追加の操作なしで、それがあるため、コンパイル時の定数。
オペランドの1のような、コンパイル時定数ではない場合
char c = 'a';
String foo = c + "bee";
ほとんどの地域で使用されるよう最適化された変異体は、Javaの8(包括的)へのJava 5のすべてのコンパイラでない場合
char c = 'a';
String foo = new StringBuilder().append(c).append("bee").toString();
参照してください、この答えを。Javaの9以降では、異なるアプローチが使用されます。
結果の動作は、必ず指定のようになります。