倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

あんたに GDK の何が分かるっていうの!? (Object 編1)

最近 Java 8 の Stream による Map/Reduce 処理の API をあれこれイジってて、GDK の同様のメソッド群と比べてみようと思い GDK の API 見てたんですが、each() とか collect() とかが Object クラスに定義されてて List や Collection の前に Object クラスから見ていかないといけないみたい。 まぁこれは配列でも同じメソッド使いたいからとかいうことなんでしょうかね。 ということで、今回から何回かにわたって GDK が Object クラスに追加しているメソッドを見ていきます。

目次

一応、第1目的はコンテナ・メソッドなので、それ以外のものは軽く流す感じで。 使用している Groovy のバージョンは 2.1.4 です。

言語サポート

まずは Groovy の制御構造などとともに使える特殊メソッド。 なんか呼び方があったような・・・ 扱うメソッドのシグニチャは以下の通り:

boolean asBoolean()
Object asType(Class type)
boolean isCase(Object switchValue)

boolean is(Object other)

それぞれのメソッドをもう少し詳しく見てみると

メソッド 返り値 since 説明
asBoolean() boolean 1.7.0 オブジェクトを boolean 値に変換。 if の条件式などで使える。
asType(Class) Object 1.0 強制型変換を行う。 as キーワードとともに使える。
isCase(Object) boolean 1.0 オブジェクトが表す条件に合うかどうかをテストする。 in や case とともに使える
is(Object) boolean 1.0 Java の == 演算子と同じ*1

といった感じ。 では、それぞれのメソッドを試してみましょう。 まずは asBoolean() メソッド:

assert 1.asBoolean() == true
assert 0.asBoolean() == false    // 整数値 0 は false

assert 1.0.asBoolean() == true
assert 0.0.asBoolean() == false    // 浮動小数点数の 0.0 も false

assert 'a'.asBoolean() == true
assert ''.asBoolean() == false    // 空文字列は false

assert ['a'].asBoolean() == true
assert [].asBoolean() == false    // 空リストは false

assert [a:3].asBoolean() == true
assert [:].asBoolean() == false    // 空マップも false

assert null.asBoolean() == false    // null も false、というかメソッド呼び出しできる

空文字列、0, 0.0, 空リスト、空マップ、null などは false を返します。 他にも Matcher や Iterator が false を返す場合もあるようです。 詳しくは『プログラミングGROOVY』を参照のこと。 上記のコードでは、asBoolean() を明示的に呼び出す必要がないものもありますが、こちらの方が値が分かりやすいかと思って付けてます。 次は asType() メソッド。 これは直接 asType() メソッドを呼び出すよりも as キーワードで使う方が分かりやすいかと:

// char 型の定数(Groovy ではシングルクォートも文字列を生成)
def ch = 'a' as char

// 配列の生成
def array = (0..10) as double[]
array.each{ println it }

// 文字列から BigDecimal へ変換
def d = "1.0" as BigDecimal
assert d + 2.0 == 3.0

// SAM (single-abstract-method) 型への変換
import java.awt.event.ActionListener
def al = { e -> println("I'm ActionListener") } as ActionListener
assert al instanceof ActionListener

Java 8 で導入されるラムダ式は SAM (single-abstract-method) 型へ自動で変換してくれますが、もちろん Groovy でも(既に)サポートされてます。 次は isCase() メソッド。 in, case 文とともに用いることが多いと思いますが、一見分かりにくいので isCase() メソッドを使ったものも書いてます:

assert (~/\w+/).isCase("abc")    // 正規表現
assert "abc" in ~/\w+/

assert String.isCase("abc")    // 型テスト instanceof
assert "abc" in String

assert [0, 1, 2, 3].isCase(3)    // リストの要素か?
assert 3 in [0, 1, 2, 3]

assert (0..10).isCase(3)    // 範囲内の要素か?
assert 3 in (0..10)

assert [a:1, b:2, c:3].isCase('a')    // 得られる値の asBoolean() が true を返すか?
assert 'a' in [a:1, b:2, c:3]

assert { it.size() == 3 }.isCase("abc")    // クロージャの評価が true か? (it が "abc")
assert "abc" in { it.size() == 3 }

in キーワードを使うと isCase() が呼ばれるオブジェクトと引数の位置が逆転するので注意。 右結合演算子っぽい感じ(Groovy に右結合とかないけど)。 最後は is() メソッド。 これは Java の == 演算子と同じです。 Groovy では == は Object#equals() メソッドによる評価になってるので、代わりに is() メソッドが定義されてます:

def s0 = new String('a'), s1 = new String('a')
assert s0 == s1    // 値が同じ
assert !s0.is(s1)    // 別のオブジェクト

プロセス・スレッド用メソッド

プロセスやスレッドに関するメソッド:

static void sleep(long milliseconds)
static void sleep(long milliseconds, Closure onInterrupt)

void addShutdownHook(Closure closure)

sleep() は「Thread.sleep(...)」と書くのが面倒なので「sleep(...)」だけでスリープできるようにしてるんでしょうね。 インターラプトされたときの処理も指定できるようになってます。

メソッド 返り値 since 説明
sleep(long) void 1.0 引数で指定されたミリ秒だけスリープする。
sleep(long, Closure) void 1.0 引数で指定されたミリビョウだけスリープする。 スリープ中にインターラプトされた場合は、第2引数のクロージャが実行される。
addShutdownHook(Closure) void 1.5.0 JVM が終了する際に実行される処理を追加する。

サンプルはこんな感じ:

// sleep(long)
sleep(1000)

// sleep(long, Closure)
import java.util.concurrent.*
def service = Executors.newCachedThreadPool()
service.submit{
    sleep(60000){
        println("I'm interupted")
        throw new RuntimeException()
    }
}
service.shutdownNow()    // 実行中のスレッドはキャンセル(インターラプト)される

// addShutdownHook()
addShutdownHook{
    println("shut down now.")    // JVM 終了時に出力
}

// たぶん、こんなのと同じ
Runtime.getRuntime().addShutdownHook(new Thread({ println("shut down now!") }))

まぁ、デバッグ時に使うことが多いんじゃないでしょうか。

かなりザッとですが Groovy 言語的に特別な意味をもったメソッドと、プロセス・スレッド関連のメソッドを見てきました。 次回はプロパティ・リフレクション関連のメソッドを見る予定。

追記
isCase() メソッドの箇所で、Map の isCase() が「キーとして値を含むかどうか」の真偽値を返すと書いてましたが、正しくは「引数をキーにして得られた値の asBoolean() が true かどうか」を返します。 キーとして存在しない場合に false を返すのは同じですが、キーとして存在する場合でも false を返すことがあります:

def map = [a:1, b:0]

assert map.isCase('a') == true
assert map.isCase('b') == false
assert map.isCase('c') == false

プログラミングGROOVY

プログラミングGROOVY

  • 作者: 関谷和愛,上原潤二,須江信洋,中野靖治
  • 出版社/メーカー: 技術評論社
  • 発売日: 2011/07/06
  • メディア: 単行本(ソフトカバー)
  • 購入: 6人 クリック: 392回
  • この商品を含むブログ (155件) を見る

*1:Groovy では == 演算子は equal() メソッドによる評価と同じ