java:通常のクラスと匿名クラス(無名クラス)の書き方の比較

以前の記事で「通常のクラスと匿名クラスの書き方の比較を見たい」という意見があったので、少し補足を行います。

サンプルコードの通り、匿名クラスの場合、クラスに名前を付ける必要が無く、またオブジェクト生成と同時に処理を定義することができます。
これにより、以下のようなメリットがあります。

  • 記述を簡潔にできる
  • 使い捨てのクラスを定義でき、使い捨てであるという意図も明確にできる
  • (ソースファイル名とクラス名を同じにする場合)管理が容易になる

【サンプルコード】

・AnonymousClass.java

・AnonymousSubClass.java

・AnonymousInterface.java

・AnonymousImplementsClass.java

・AnonymousMain.java

【実行結果】


良い意見やコメントを頂いた時は、今回のような形で答えていきたいと思います!

java:引数で渡した参照型変数をメソッド内で変更する書き方について

参照型変数を引数としてメソッドに渡し、呼び出し先のメソッドの中でその参照型変数に変更を入れた場合、呼び出し元でもその変更内容を参照することができます。
ソースコードで言うと、以下のような形で呼び出し元に影響を与えることができます。
(isDisplay[0]の変更は呼び出し元にも反映されます。実行すると、”Hello World!”が出力され、”Error!”は出力されません。)

このような書き方は、C言語のレガシーなコードではよく見かけますが、javaではあまり見かけることがないと思います。
レガシーな現場に入ったことが無い方は、見慣れていない、違和感がある、と感じる方が多いと思います。

javaでは、以下のように戻り値により呼び出し元に影響を与える書き方の方が主流です。

ビジネスロジックを知り尽くしている場合は、前者のようにメソッドに参照型変数を渡してメソッドの中で好きに変更させる形にした方が楽にコーディングできます。
しかし、ビジネスロジックをよく知らない担当者がソースコードを調査したり改修したりする場合、後者のように戻り値を通して呼び出し元に影響を与える形にしないと、読む必要があるソースコードの範囲が広がり、調査・改修が困難になります。
今回の例で言うと、”isDisplay[1]”に変更が入っていないことを知るために、前者のコードではメソッドの中まで見る必要がありますが、後者のコードではメソッドの中まで見る必要はありません。

現在の開発現場では、複数の担当者が入れ替わり立ち替わりでソースコードを改修し続けるのが主流ですので、後者の書き方の方が望まれます。
現行のソースコードが既に前者の形で書かれているのであれば、それに合わせた方が良い場合もありますが、そうではないなら後者の書き方で書くべきでしょう。


いかがでしたでしょうか。

新しい技術に触れることが多い技術者が前者のようなソースコードを見て戸惑っていたので、今回の記事を書きました。
今からソースコードを書くなら後者の書き方を推奨するのですが、前者のような書き方もあるというのは覚えておいて損は無いかもしれません。

java:例外発生後に例外のメッセージを書き変える

例外オブジェクトにはメッセージが格納されており、getMessage()メソッドでそのメッセージを取得することができます。
しかし、このメッセージはコンストラクタでのみ設定可能であり、メッセージを後で変更するメソッドは用意されていないため、例外クラスに用意されている手段では例外発生後にメッセージを書き変えることはできません。

しかし、リフレクションを使用することで、メッセージを後で書き変えることが可能です。
メッセージはThrowableクラスのprivateのクラス変数”detailMessage”に保持されるため、これをリフレクションで書き変えます。

サンプルコードは以下の通りです。

【サンプルコード】

・ExceptionTest.java

【実行結果】

・コンソール(標準出力)

・コンソール(標準エラー出力)


ちなみに、リフレクション時に発生してしまう標準エラー出力ですが、(試していませんが)Java8では出ないようです。
筆者の環境(Java10)だと出てしまいます。

そこで以下の2つの手段を試しましたが、何れもエラー抑止はできませんでした。

1.JVM引数で抑止

“–illegal-access=deny”を指定したら逆に異常終了するようになってしまいました。

2.標準エラー出力の出力ストリームを変更

通常、”System.setErr(自作PrintStreamオブジェクト);”を記述することで標準エラー出力の出力先を変更し、コンソールに出力されないようにすることができるのですが、今回のケースではそれができませんでした。
“System.err.close();”を記述した場合はコンソールへの出力を抑止することができたので、リフレクション時のWARNINGメッセージでは”System.err”を直接使用しているのではないかと思います。
なお、”System.err”はクローズしたらリオープンすることができないので、”System.err.close();”を実行してしまうと、以降は予期せぬ例外等が発生しても標準エラー出力として出力できなくなってしまいます。
(”System.err.close();”を実行した後に”System.setErr(System.out);”を実行して、予期せぬ例外等も全て標準出力として出力することならできますが…)


いかがでしたでしょうか。

今回の記事では、例外発生時のメッセージを後から書き変えられることを確認しましたが、標準エラー出力が出力されることを考えると、このようなソースコードはできる限り書くべきではないと思います。
どうしても書き変え可能な変数を伝播させたいのであれば、独自例外クラスに独自のクラス変数を定義してそれを伝播させる等の工夫をするべきだと思います。

java:例外を先に生成して後でthrowする

通常のjavaのソースコードでは、例外を発生させると同時にthrowしていると思います。
しかし、例外クラスもクラスの一つであり、newするとオブジェクトが生成されますので、先に例外クラスのオブジェクトを生成し、オブジェクトとしてやりとりした後、後でthrowすることが可能です。

以下、サンプルコードです。
FileNotFoundExceptionを生成した後にIOExceptionを生成・上書きし、IOExceptionを返すというサンプルコードです。

【サンプルコード】

・ExceptionTest.java

【実行結果】


いかがでしたでしょうか。

今回の記事では、先に例外クラスのオブジェクトを生成して後でthrowできることを確認しました。
しかし、通常、後でthrowするようなソースコードは書かないと思います。
少なくとも、今回のような例では、フラグ変数でどの例外を返すかの情報を保持し、後で例外オブジェクトを1回だけ生成するべきです(オブジェクトの生成にはリソースが必要なため)。

実務の中で後からthrowしたいという話が出たので、そもそもできるのかというのを確認したのですが、できたとしてもトリッキーな印象は否めないので、このようなソースコードを書くことには慎重になった方が良いと思います。

Vue.jsに出てくるコロン(v-bind)とアットマーク(v-on)について

Vue.jsのコードに時折コロン(:)やアットマーク(@)が出てきて戸惑う人がいるかもしれませんが、これは省略記法です。
それぞれ、v-bind、v-onを指しています。

Vueオブジェクトの変数や関数をHTML側から参照するために、v-bindやv-onを使用します。

以下、サンプルコードです。

【サンプルコード(v-bind)】

【実行結果(v-bind)】

以下のように、Vueオブジェクトの変数の値とHTMLを結びつけることができます。

【サンプルコード(v-on)】

【実行結果(v-on)】

以下のように、Vueオブジェクトの関数を呼び出すことができます。
これは、ボタン1とボタン2の両方で同じ動きになります。


いかがでしたでしょうか。

省略記法は公式チュートリアルにて説明されていますが、忘れた時に実務で出くわすと戸惑うと思います。
“:”は”v-bind”、”@”は”v-on”、というのは覚えておくと良いでしょう。