Javaの例外処理について、もうちょい調べてみました

f:id:ts0818:20190525093356j:plain

「Ah 長いレールの上を 歩む旅路だ 風に吹かれ バランスとりながら
    Ah “答え"なんて どこにも見当たらないけど それでいいさ 流れるまま進もう
    手にしたものを失う怖さに 縛られるぐらいなら 勲章などいらない(Mr.children『【es】 〜Theme of es〜』)」

勲章もいらなくないわけではないけども、例外処理はもっといらなくないということで、はい、どうもボクです。

というわけで、今回は、Javaの例外処理について、もうちょい調べてみました。主に、finally 句についてですかね。

 

By the way、ブロックチェーンの合同企業説明会に参加してきました。11時開始だったんですが、13時ぐらいからの参加になってしまった...

withb.co.jp

⇧  なんでも、株式会社withB っていう会社が主催?しておるそうです。

withb.co.jp

⇧  顧問の藤本 真衣さんの、『海外に3000円の寄付をする際に、手数料が8000円という現実。その現象を解決してくれるのが仮想通貨。仮想通貨の可能性にワクワクしている』という言葉がとても印象的でした。 っていうか、海外の手数料って、エゲツないっすね...。

 

マウントゴックスの事件で時の人になった、マルク・カルプレス 氏の話も聞けました~。本を出すみたいです。とう言うか、日本語むっちゃペラペラでした。警護の人もいてびっくりでした。


仮想通貨3.0

 

『藤本 真衣 × マルク・カルプレス』の対談で、

「仮想通貨って、株なんかのように投資としてのイメージが定着してしまっている昨今ではあるけれども、本来は普通のお金のように使われるものを目指していたはずと。」

と仰っていましたかね。ブロックチェーンの技術を活用できる技術が発展・浸透すれば、仮想通貨の時代が来ますかね。

 

個人的には、

nayuta.co

⇧  株式会社Nayuta の 代表取締役の栗元憲一さんの技術の話がとても面白かったです。「ライトニングネットワーク」という技術も初めて知りました。

ライトニングネットワークとは、ブロックチェーン(ほとんどの場合ビットコイン)上で動作する「セカンドレイヤー」ペイメントプロトコルである。ライトニングネットワークは理論的には参加ノードの間での高速なトランザクション処理を可能にし、またビットコインのスケーラビリティ問題の解決策と謳われている。ライトニングネットワークは資金の管理券を委譲することのない双方向ペイメントチャネルを通して暗号通貨マイクロペイメントを行うピア・ツー・ピアのシステムを特徴としている。ライトニングネットワークの実装はアトミックスワップを簡素化する。

ライトニングネットワーク - Wikipedia

⇧  Wikipedia さんの説明でもあるように、ブロックチェーンのレイヤー層の上に、「ライトニングネットワーク」というレイヤー層を構築し、その上位層にアプリケーションのレイヤー層が来るイメージですかね。

なんで、「ライトニングネットワーク」が必要かと言うと、ブロックチェーントランザクション処理の性能が如何ともし難いことが理由らしいです。

ビットコインのスケーラビリティ問題とは、ビットコインにおけるブロックチェーンのブロックサイズが1メガバイト(MB)に制限されている結果起きている問題である

1MBよりも大きいブロックは無効なものとして自動的にネットワークから排除されるビットコインブロックは、最後のブロックが作成されてからビットコインネットワーク上でトランザクションを処理する。 これにより、1秒間に3~4トランザクション(理論上は最大7トランザクション)を処理できるようになっている

ビットコインのスケーラビリティ問題 - Wikipedia

⇧ ちなみに、

virtual-coiner.info

⇧  上記サイト様によりますと、ビットコインキャッシュビットコインの32倍ぐらいの処理速度らしいんですが、一般的な決済システムと比較するとお話にならないぐらいの数しかトランザクションを捌けないらしい。

それを解決するのが、「ライトニングネットワーク」らしいっす。

あと、『マネー・ロンダリング』の防止なんかの対策も考えられているようです。

 

だいぶ、話が脱線してしまったんですが、今回は、Javaの例外処理でしたね。

ts0818.hatenablog.com

⇧  この頃、まだ良く分かってなかったな~、いまも良く分かってないけど...

そんでは、レッツトライ~。

 

Javaの例外処理についてあれこれ

Javaの例外処理については、

qiita.com

qiita.com

daisuke-m.hatenablog.com

⇧  上記サイト様が詳しいです。

Javaの例外処理で、プログラミング的には、

  1. try with resource文(Java 7 以降)
  2. try catch文(finally 句なし)
  3. try catch文(finally 句あり)

の3つがあると思うんだけれど(というか、他にあるのか分からん)、今回は、「3.try catch文(finally 句あり)」のパターンについて考えていきたいと。

ちなみに、「1.try with resource文(Java 7 以降)」にもハマりどころが存在するらしく、

qiita.com

⇧  上記サイト様が詳しいです。 

 

finally句の罠

try catch 文によって、例外をキャッチすることができるわけですが、try catch 文には、finally 句ってものが存在すると。

で、こいつが曲者らしいんですよ。

qiita.com

Java の try ~ finally と return の良く知られた闇として「finally 句にて値の return もしくは例外のスローをするといろいろとまずい」というものがある。

検索すれば詳細な情報はすぐ出てくると思うので、どうしてまずいのかだけを簡潔に述べておくと try 句での return や例外を finally 句で完全に上書いてしまえる、という理由による。

すると最初に発生した例外を無視して別の例外をスローできたり、全く何もなかったかのような正常な return を行なえる状態になってしまうのだ。

[Javaの小枝] try ~ finally と return のもう一つの闇 - Qiita

⇧  上記サイト様が仰っておられるように、fainally 句 って地球に隕石が落ちてこようが必ず実行されるよね~、ってことらしい。

つまり、最終的に、あらゆる値は、finally 句の処理によって上書きされる...って思ってたんだけど、その認識だけでは足りないんであると。

しかしもう一つ、 try ~ finally と return には闇が見え隠れしていることを指摘しておく。実は finally 句ではなく try 句で return していても闇コードになることがあるのだ。

[Javaの小枝] try ~ finally と return のもう一つの闇 - Qiita

⇧  上記サイト様で仰っておられるように、return が、さらなる闇を加速させるということのようです。

 

というわけで、実際に試してみる。

Eclipseで適当なJavaプロジェクトを作成し、クラスも作成で。

f:id:ts0818:20190526205207p:plain

まずは、Exceptionが、finally 句 で上書きされちゃうの?ってのを検証。

public class TestFinally {

  @SuppressWarnings("finally")
  public static void main(String[] args) {
    int number = 0;
    // TODO 自動生成されたメソッド・スタブ
    try {
      number = Integer.parseInt("ハラショー");
    } catch (NumberFormatException e) {
      System.out.println(number);
      // TODO 自動生成された catch ブロック
      throw new NumberFormatException();
    } finally {
      throw new IllegalArgumentException();
    }    
  }
}
    

んで、実行。

f:id:ts0818:20190526205435p:plain

f:id:ts0818:20190526205627p:plain

はい、見事に上書きされました。

んで、return 句 の検証。

public class TestFinally {

  public static void main(String[] args) {
    System.out.println("最終的な値:" + takeNumber("ハラショー"));
  }
  
  public static int takeNumber(String numberStr) {
    int number = 0;
    // TODO 自動生成されたメソッド・スタブ
    try {
      number = Integer.parseInt(numberStr);
      
    } catch (NumberFormatException e) {
      System.out.println("catch句:" + number);
      return number;
      // TODO 自動生成された catch ブロック
      
    } finally {
      number =+ 3;
      System.out.println("finally句:" + number);
      
    }
    System.out.println("大外:" + number);
    return number;
  }
}

んで、実行。

f:id:ts0818:20190526210620p:plain

という...つまり、catch 句 の中の変数numberの値と、finally 句 の中の変数numberの値は、同じint型で同一の変数ではあるのだけれど、参照が異なるらしい。これは、int型がプリミティブな型であることに由るらしい。

String型などのイミュータブルな型も同様な結果になるらしい。

が、StringBuilder型などのように、ミュータブルな型の場合は、参照が同一となるらしい。

ちなみに、finally 句 のほうでもreturn するよう実装し、

public class TestFinally {

  public static void main(String[] args) {
    System.out.println("最終的な値:" + takeNumber("ハラショー"));
  }
  
  @SuppressWarnings("finally")
  public static int takeNumber(String numberStr) {
    int number = 0;
    // TODO 自動生成されたメソッド・スタブ
    try {
      number = Integer.parseInt(numberStr);
      
    } catch (NumberFormatException e) {
      number =+ 100;
      System.out.println("catch句:" + number);
      return number;
      // TODO 自動生成された catch ブロック
      
    } finally {
      number = +3;
      System.out.println("finally句:" + number);
      return number;
    }
    // System.out.println("大外:" + number);
    // return number;
  }
}

んで、実行。

f:id:ts0818:20190526221324p:plain

finally 句 の return が、優先されるらしい...う~ん、Javaの評価順序、よく分からん...。まぁ、「@SuppressWarnings("finally")」なんて付けること普通は無いはずだし、そんな気にしなくても良いんですかね?

とりあえず、「try catch文(finally 句あり)」は闇が深いということですかね...

今回はこのへんで。