Open9

Java Silver (11) 黒本 間違えた問題まとめ

りすりす

Section 1

5

エントリポイント(mainメソッド)はpublicである必要がある
publicでなくてもいいのはそのメソッドを含んだクラス

8

起動パラメーターは、スペースのみ区切り文字になる
"a"b"が無視されて単にabと同じ

りすりす

Section 2

3

数値リテラルにおいて、_は基本どこでも使える
ただし、必ず数字と数字の間でないといけないので、先頭や末尾、., L, F, b, xの前後は無理
例えば0_123は8進数のリテラルだが、数字と数字の間なので問題ない

5

変数名などの識別子で$,_以外の記号は基本使えない
基本的にUnicode文字なら使えるが、構文で使われる記号は使えないので
あと数字から始まるのはダメ

13

凡ミス、数えられなかったらしい
indexは、begin: inclusive, end: exclusiveの半開区間
endがinclusiveだとclosedとメソッド名などにつけて閉区間と明記する

14

String::replaceは全ての一致した文字列を置き換える
String::replaceAllとの違いは正規表現を使えるかどうか(~Allは使える)

17

String::concat, StringBuilder::append

19

null + "a"はぬるぽにならない

20

StringBuilder::capacityは初期文字数 + 16
Javadocに明記してある

The initial capacity of the string builder is 16 plus the length of the string argument.

21

凡ミス、reverseを読み落としたらしい

りすりす

Section 3

1

代入演算子は計算が終わってから値を返す…ように見える
実際は右側から処理されるからそうなるだけ

int a = 5;
int b = 5 + (a += 3); // かっこ必須
System.out.println(b); // 13

3

数値のダウンキャスト(?)はコンパイルエラーになる

ただし、int からでかつ、対象の型の範囲内なら問題ない
byte: -128~127 = -2^7~2^7-1 (signed 8 bit)
short: -32768~32767 = -2^15~2^15-1 (signed 16 bit)

long -> int, double -> float は範囲内でもダメということ

4

計算ミス…?
インクリメント演算子は、後置の場合値を返してから1増やし、前置の場合1増やしてから値を返す
演算子のある位置でインクリメントすると考えればよい

10

Object::equalsの引数はObject!!!

14

String::internはコンスタントプールから返すメソッド

18

else ifは間で改行できない
改行すると、elseブロックの中にifがあるのと同じになる

19

switch文の条件に使えるのは、int以下の整数型とそのラッパー、あとcharStringEnum
longは使えない、これはパフォーマンス的な理由だったはず
floatdoubleは浮動小数点数で誤差があるので、booleanはif使えばいいので使えない

20

case値に指定できるのは条件と同じかcompatibleな型、またfinalである必要がある
effectively finalではダメ

りすりす

Section 4

8

for文の更新文(最後のやつ)は,で複数列挙できる

12

String[] arr = { "a", "b", "c" };
for (var s : arr) {
  s = "";
}
System.out.println(Arrays.toString(arr));
// abc

拡張for文での変数は配列の参照先を持つだけで配列を直接変更できるわけではない
以下と同じ

for (var i = 0; i < arr.length; i++) {
  var s = arr[i];
  s = "";
}

内部的にIteratorが用いられているからだと思う

13

do-while文は最初に1度のみwhile文の中を実行しているだけ

14

問題文勘違いしただけ

16

ラベル結構色んなものにつけれるらしい
変数宣言以外大体つけれそう?
https://qiita.com/zr_tex8r/items/08ae8bf08aa29f18535c

17

どうやら不等号の向きが読めないらしい

りすりす

Section 5

2

int[] a;
int b[];

多次元配列の場合これらを混ぜて書ける

3

型を表す[]に数は書けない

4

配列の生成について
int以下の整数型のみlengthに指定できる (char可, float, double, long不可)
負の数の場合、NegativeArraySizeException
型は次元が合っている必要がある(Object[]の場合配列を含められるので適当でもコンパイルは通る)
var a[] はダメ

5

配列の要素が初期化されてないからぬるぽ

7

new int[] {}が基本で、{}に省略できるのは宣言と同時のときだけ
またこの時要素数は指定できない

りすりす

Section 6

15

到達不可能な文があるとコンパイルエラー

16

メソッド名と引数の型/順番が同じものをオーバーロードと呼ぶ
戻り値の型が違うだけだとコンパイルエラーになるしオーバーロードとは呼ばない
また、全く同じメソッドもオーバーロードとは呼ばない、そりゃそう

18

アクセス修飾子が違ってもオーバーロードではない

20

クラス名と同じメソッドを定義した場合、コンパイルエラーにはならず普通に動く

21

イニシャライザは、スーパーコンストラクタの後、コンストラクタの前に実行される

22

変数がstaticなの気づかなかった…

27

protectedは他のパッケージから(継承してなければ)アクセスできない、当たり前

28

カプセル化はアクセッサーメソッドのアクセス修飾子関係ない

りすりす

Section 8

3

ラムダ式のスコープはそれを含むブロックと同じ
匿名クラスとは違うところ

4

effectively final でないローカル変数はラムダ式の中で使えない

りすりす

Section 10

2

Comparatorについて
compare(T o1, T o2)は、o1 -> o2 の場合は負、o2 -> o1 の場合は正を返す
o1 - o2 を返すと覚えると楽

3

ComparablecompareTo(T o)について

o1.compareTo(o2) == Comparator.naturalOrder().compare(o1, o2)

4

Characterにどんなメソッドがあるか覚える
https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/lang/Character.html

10

原型(Raw type)でもダイヤモンド演算子を使える

11

List.remove(Object o)はListに含まれる最初の同値の要素を削除する
これはListインターフェースのメソッド契約に記載されているもの

Removes the first occurrence of the specified element from this list, if it is present (optional operation).
https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/util/List.html#remove(java.lang.Object)

12

拡張for文の中でListから削除した場合、後の要素が繰り上がる

13

拡張for文でListから要素を削除した後にアクセスするとConcurrentModificationExceptionを吐く
https://qiita.com/ukitiyan/items/adec43ea77cb78169e80
以下スタックトレース

Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
	at io.github.risu729.test.Main.main(Main.java:13)

16

Arrays::compareは辞書順、Arrays::mismatchが返すindexの要素同士をcompareする