回答編集履歴

1

追記

2018/05/29 06:23

投稿

KSwordOfHaste
KSwordOfHaste

スコア18394

test CHANGED
@@ -41,3 +41,55 @@
41
41
  System.out.println(greeting); // 必ず設定されている保証の元で参照する
42
42
 
43
43
  ```
44
+
45
+
46
+
47
+ ---
48
+
49
+ 追記:本件に直接関係ないですが、mts10806さんがコメントくださった点について少し追記してみます。以前似たようなQ&Aがあったかと思いますが、自分は「変数のとりあえずの初期化」は避けます。理由はなるべく変数をfinalとして扱いたい(つまり途中で値が変わる変数にはしたくない)からです。
50
+
51
+
52
+
53
+ 途中で値が変化する変数ももちろん使いますが使わずに済ませられることも多いです。Javaの仕様はいくぶん厳格でfinalでない変数は内側のスコープからアクセスさせてやんないという仕様なのでそういう点からもなるべくfinalにしておこうと考えます。(本末転倒な論理ですね。本来は極力finalにしようってのが本質だと思います。)
54
+
55
+
56
+
57
+ ```java
58
+
59
+ String greeting; // (A)
60
+
61
+ if (...) {
62
+
63
+ greeting = ...;
64
+
65
+ } else if (...) {
66
+
67
+ greeting = ...;
68
+
69
+ } else {
70
+
71
+ greeting = ...;
72
+
73
+ }
74
+
75
+ Button button = new Button("Hi");
76
+
77
+ button.setOnAction(ev -> System.out.println(greeting)); // <= (B)
78
+
79
+ ```
80
+
81
+
82
+
83
+ 例えば上のコードだとgreetingはfinalと見做してくれるためラムダ式の本体(B)で参照できます。これを(A)で「とりあえず初期化」としてしまうとfinalではなくなるため(B)で参照できなくなるという「面白くないこと」になります。
84
+
85
+
86
+
87
+ この辺り言語によって違うようですが、JavaScript, Python, Scala, C#などだとfinalじゃなきゃ内側のスコープで参照できないという制約はありません。どうも大半のモダンな言語はそういう制約は課してないようです。しかしこれがJavaだと「副作用を持たない行儀良いコードだけ外側のスコープの変数をアクセスさせてやる」といった気難しいオジイチャンのような仕様です。
88
+
89
+
90
+
91
+ 「finalでないものがアクセスできないなんて言語機能が足りてないんじゃないの?」と思ったこともありますが、「まぁまぁそういわずfinalにすることを意識する方がいいと捉えよう」と前向きに考えるようにしました。
92
+
93
+
94
+
95
+ (finalじゃない変数しか内側からアクセスできないってのはJavaぐらいかも知れません。実際は行儀良いコードにだけ内側からのアクセスを許すという意図があるのか、単に実装がめんどかったのでまぁできなくていいよねぐらいのノリなのか本当のところは自分には分かりません。ただ変更可能なローカル変数を内側のスコープからアクセスできるようにするとそれなりの性能的代償があるとは思います。ScalaやC#はその代償をプログラマーが意識していない実装の中でこっそり支払っています。そうした細かい点を気にせず制限なく使える言語がいいのか、制約がある理由を把握した上で使う方がよいのか・・・自分には何とも言えません。)