はじめに
Java Silver(SE 21対応)試験対策として、文字列操作に関する問題を10問まとめました。Stringのイミュータブル性や文字列プール、StringBuilderの挙動など、試験で頻出のポイントを中心に構成しています。
問1 ⭐ Stringのイミュータブル性
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
String s = "Hello";
s.concat(" World");
s.toUpperCase();
System.out.println(s);
}
}
A. HELLO WORLD
B. Hello World
C. HELLO
D. Hello
解答と解説
正解: D
Stringはイミュータブル(不変) です。concat()やtoUpperCase()は新しいStringオブジェクトを返しますが、元のオブジェクトは変更されません。
戻り値を変数に代入しない限り、元の文字列には影響がありません。
String s = "Hello";
s = s.concat(" World"); // 戻り値を再代入
System.out.println(s); // "Hello World"
問2 ⭐⭐ 文字列プール
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "Hel" + "lo";
String s3 = "Hel";
String s4 = s3 + "lo";
System.out.println(s1 == s2);
System.out.println(s1 == s4);
}
}
A. true, true
B. true, false
C. false, true
D. false, false
解答と解説
正解: B
-
s1 == s2→"Hel" + "lo"はコンパイル時にリテラル同士の結合として最適化され、"Hello"になります。文字列プールの同じオブジェクトを参照するためtrue -
s1 == s4→s3 + "lo"は変数s3を含むため、コンパイル時定数ではありません。実行時に新しいStringオブジェクトが生成されるためfalse
s3をfinalにすると結果が変わります。
final String s3 = "Hel";
String s4 = s3 + "lo"; // コンパイル時定数になる
System.out.println(s1 == s4); // true
問3 ⭐ substringメソッド
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
String s = "abcdef";
System.out.println(s.substring(2, 4));
}
}
A. cd
B. cde
C. bcd
D. bcde
解答と解説
正解: A
substring(beginIndex, endIndex)は、beginIndex(含む)からendIndex(含まない)までの部分文字列を返します。
インデックス: 0 1 2 3 4 5
文字: a b c d e f
^ ^
begin(2) end(4)
インデックス2(c)から4の手前(d)まで → "cd"
endIndexが「含まない」ことを忘れがちなので注意してください。
問4 ⭐⭐ indexOfとcharAt
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
String s = "Java Silver";
System.out.println(s.indexOf("va"));
System.out.println(s.charAt(5));
}
}
A. 2, S
B. 3, S
C. 2, i
D. 2, S
解答と解説
正解: A
indexOf("va"): 部分文字列"va"が最初に見つかるインデックスを返します。
インデックス: 0 1 2 3 4 5 6 7 8 9 10
文字: J a v a S i l v e r
^ ^
"va"はインデックス2から始まる(ではなく...)
"va"はvがインデックス2にあるので、返り値は2です。
charAt(5): インデックス5の文字はS(スペースはインデックス4)。
出力は2とSです。
問5 ⭐⭐ replaceメソッド
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
String s = "aabbcc";
String result = s.replace("bb", "B").replace("cc", "C");
System.out.println(s);
System.out.println(result);
}
}
A. aaBbCcとaaBbCc
B. aabbccとaaBC
C. aaBCとaaBC
D. aabbccとaaBbCc
解答と解説
正解: B
Stringはイミュータブルなので、replace()は新しい文字列を返します。元のsは変更されません。
処理の流れ:
-
s.replace("bb", "B")→"aaBcc"(新しいString) -
"aaBcc".replace("cc", "C")→"aaBC"(新しいString) -
resultは"aaBC" -
sは元のまま"aabbcc"
メソッドチェーンでreplaceを連結しても、各呼び出しで新しいオブジェクトが生成されます。
問6 ⭐ trimとstrip
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
String s = " Hello ";
System.out.println("[" + s.trim() + "]");
System.out.println("[" + s.strip() + "]");
System.out.println("[" + s.stripLeading() + "]");
System.out.println("[" + s.stripTrailing() + "]");
}
}
A.
[Hello]
[Hello]
[Hello ]
[ Hello]
B.
[Hello]
[Hello]
[ Hello]
[Hello ]
C.
[ Hello ]
[Hello]
[Hello ]
[ Hello]
D. コンパイルエラー
解答と解説
正解: A
-
trim(): 先頭と末尾のASCII空白文字(コードポイント\u0020以下)を除去 -
strip(): 先頭と末尾のUnicode空白文字を除去(trim()より広範囲) -
stripLeading(): 先頭のUnicode空白文字を除去 -
stripTrailing(): 末尾のUnicode空白文字を除去
半角スペースの場合はtrim()とstrip()の結果は同じです。全角スペース等のUnicode空白文字の場合に差が出ます。
stripLeading()は先頭のみ除去するので末尾のスペースが残り、stripTrailing()は末尾のみ除去するので先頭のスペースが残ります。
問7 ⭐⭐ StringBuilderの操作
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("abcde");
sb.delete(1, 3);
sb.insert(1, "XY");
System.out.println(sb);
}
}
A. aXYde
B. aXYbde
C. aXYcde
D. XYade
解答と解説
正解: A
StringBuilderはミュータブル(可変)で、メソッド呼び出しが元のオブジェクトを直接変更します。
- 初期状態:
"abcde" -
delete(1, 3): インデックス1(含む)から3(含まない)を削除 →"ade" -
insert(1, "XY"): インデックス1の位置に"XY"を挿入 →"aXYde"
deleteの第2引数は「含まない(exclusive)」であることに注意してください。substringと同じ考え方です。
問8 ⭐⭐ StringBuilderのreverse
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello");
sb.reverse();
System.out.println(sb.append(" World"));
}
}
A. olleH World
B. Hello World
C. dlroW olleH
D. World olleH
解答と解説
正解: A
-
sb.reverse()→"Hello"が反転して"olleH"になる(sb自身が変更される) -
sb.append(" World")→"olleH"に" World"を追加して"olleH World"になる
StringBuilderのメソッドはthisを返すためメソッドチェーンが可能ですが、各メソッドは元のオブジェクトを直接変更している点を理解しておくことが重要です。
問9 ⭐⭐⭐ StringとStringBuilderの比較
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
String s = "Hello";
StringBuilder sb = new StringBuilder("Hello");
System.out.println(s.equals(sb));
System.out.println(sb.equals(s));
}
}
A. true, true
B. true, false
C. false, true
D. false, false
解答と解説
正解: D
-
s.equals(sb):Stringのequals()は引数がString型であるかをチェックします。StringBuilderはStringではないためfalse -
sb.equals(s):StringBuilderはequals()をオーバーライドしていません。Objectのequals()(参照比較)が使われるためfalse
StringとStringBuilderは異なる型なので、equals()でtrueになることはありません。内容を比較するには、StringBuilderをtoString()でStringに変換してから比較します。
System.out.println(s.equals(sb.toString())); // true
問10 ⭐⭐⭐ StringBuilderのメソッドチェーン
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("ABCDE");
StringBuilder sb2 = sb.replace(1, 3, "xy");
sb2.delete(0, 1);
System.out.println(sb);
System.out.println(sb == sb2);
}
}
A. ABCDEとfalse
B. xyDEとtrue
C. AxyDEとfalse
D. xyDEとfalse
解答と解説
正解: B
StringBuilderのメソッドは自分自身(this)を返します。
-
sb.replace(1, 3, "xy")→sbの内容が"AxyDE"になり、sb自身を返す。sb2はsbと同じオブジェクトを参照 -
sb2.delete(0, 1)→ インデックス0を削除 →"xyDE"。sbとsb2は同じオブジェクトなので、sbの内容も"xyDE"
-
sbの出力:xyDE -
sb == sb2: 同じオブジェクトなのでtrue
Stringと違い、StringBuilderはミュータブルです。メソッドの戻り値は新しいオブジェクトではなく、自分自身への参照です。
参考
- Oracle Java SE 21 API - String
- Oracle Java SE 21 API - StringBuilder
- Oracle Java SE 21 Language Specification - 3.10.5. String Literals
@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!