Hatena::ブログ(Diary)

プログラマーの脳みそ このページをアンテナに追加 RSSフィード

2013-11-11

Semicolonless Java8

| 20:42 |  Semicolonless Java8を含むブックマーク

JJUG CCC 2013 Fallの懇親会のLT(ライトニングトーク)でSemicolonless Java8について発表しました。

Semicolonless Java とはエクストリームプログラミング(要するにプログラミングの縛りプレイ)でルールは以下のとおりです。

  • セミコロンを用いてはいけない
  • ユニコードエスケープは不可
  • Java SEの標準APIだけを使う

Java7版についてはJavaOne Tokyo 2012のLT解説が詳しいのでそちらを参照してください。

または 公式wikiを参照してください。

Semicolonless Java7までは戻り値のないメソッドの呼び出しにはリフレクションを用いる必要がありました。

Semicolonless JavaからJavaのAPIを呼び出す場合の基本書式は以下の通りです。Java言語のリフレクションが用いられます。

if (null == インスタンスの型.class.getMethod("メソッド名", 引数の型.class, 引数の型.class, ... )

.invoke(インスタンス, 引数, 引数, ... )){}

http://wiki.livedoor.jp/semicolonlessjava/d/Hello%20world

Semicolonless Java8 ではラムダを用いることでリフレクションから解放されます。

if (null == java.util.concurrent.Executors.callable(() -> System.out.println("Hello world")).call()){}

この動きですが、Executors.callable()の引数はjava.lang.Runnable型で、ラムダの

() -> System.out.println("Hello world")

はRunnable型と解釈されます。ですからこのprintln()はRunnable.run()の実装としてふるまいます。

ただし、Runnable.run()は戻り値がvoid型でそのままではセミコロンレスに呼び出すことができません。ScheduledThreadPoolExecutor.submit()にRunnableを渡すのであれば戻り値があるのでセミコロンレスに呼び出し可能ですが、非同期実行されても困りますよね。

そこでExecutorsのcallable()を利用することにします。このユーティリティによって戻り値がvoid型のRunnable.run()は戻り値のあるCallable.call()へと変換されました。

あとはいつものようにif文で囲ってnull値と比較すればokです。

リフレクションフリーになったのでリファクタリングでもメソッド名の変更が追従できますよ。

JavaFXのHello World デモのソースは以下の通り

public class Hello extends javafx.application.Application{

    @Override
    public void start(javafx.stage.Stage stage) throws Exception {
        if (java.util.concurrent.Executors.callable(() -> stage.setTitle("Hello, World!")).call() == null){}
        for (javafx.scene.layout.AnchorPane root :
                new javafx.scene.layout.AnchorPane[]{new javafx.scene.layout.AnchorPane()}) {
            if (root.getChildren().add(new javafx.scene.control.Label("Hello, World!"))){}

            if (java.util.concurrent.Executors.callable(() -> stage.setScene(
                    new javafx.scene.Scene(root, 300, 120))).call() == null){}
            if (java.util.concurrent.Executors.callable(() -> stage.show()).call() == null){}
        }
    }

    public static void main(String... args) throws Exception {
        if (java.util.concurrent.Executors.callable(() -> launch(args)).call() == null){}
    }
}

language_and_engineeringlanguage_and_engineering 2013/11/13 03:47 秀逸なスライドの中に,new T()のお話を含めて下さりどうもありがとうございます。
もう1年半前の事となり,懐かしいですね。こちらでは,いまだに未解決問題です・・・。