• 検索結果がありません。

#13 Java開発者のための実践的Groovy入門 須江さん GCRアーカイブ main

N/A
N/A
Protected

Academic year: 2018

シェア "#13 Java開発者のための実践的Groovy入門 須江さん GCRアーカイブ main"

Copied!
59
0
0

読み込み中.... (全文を見る)

全文

(1)

Grails #13

Java 開発者 ため 実践的 Groovy 入門

2008/10/8(資料更新:2008/11/27) 日本 ビ () 須江 信洋

[email protected] [email protected]

(2)

めに - Groovy 特徴

Java 段階的 移行 可能

Java 使え

Java 文法 使え

Java (Ant,JUnit, ) 使え

硬軟 対応

必要 け型 指定

Java 統合

動的 MOP

動的 生成 選択

⇒日々 作業 幅広く使え

Java API 対話的 確認 有用

(3)

Agenda

Groovy

Java Groovy 注意

Inside Groovy

Groovy 入門編

ョン操作

制御構造

演算子 Category

XML 操作

Web/Web

い限 Groovy-1.5.6 動作確認

(4)

Groovy サバイバル イド

(5)

(Windows)

groovy.codehaus.org (groovy-

binary-1.5.6.zip) 展開

zip groovy-1.5.6 適当

(c:¥groovy ) 展開

環境変数 GROOVY_HOME 設定

- -

詳細設定 選択 環境設定

環境変数 新規 設定

変数 GROOVY_HOME

変数値: c:¥groovy¥groovy-1.5.6 ※各自 環境 合わ

設定

環境変数 変数 PATH 選択 編集

変数値 先頭 %GROOVY_HOME%¥bin; 追加

groovy v 実行 正常 起動

こ 確認

(6)

Groovy を実行

groovy Hoge[.groovy]

Groovy 実行

Groovy

groovysh

ン版対話型

Groovy

groovyConsole

GUI

SwingBuilder 構築さ

(7)

groovysh 使用上 注意

変数 定義

× def x= hogehoge

x= hogehoge

x binding 格納さ 期待通 動作

GINA 11.2.2

(8)

そ 他 手段

IDE 使う

Eclipse Groovy plug-in

Groovy +α

NetBeans 6.5(beta)

Grails こう手厚く支援

Groovy

IntelliJ IDEA

Groovy/Grails 老舗

有償 使い勝手 良好? 使

Windows Installer 使う

.groovy 実行

Gant gant 関連付け

(9)

Object Browser

最後 評価 / 参照

groovysh: inspect

groovyConsole: Ctrl+I or Script - Inspect Last

(10)

Tips

obj.class.name

/ / 一覧

obj.properties

obj.class.methods.name

obj.class.fields.name

列表現

obj.dump()

(11)

Inside Groovy

(12)

Groovy 舞台裏を探

Groovy 実行時 Java

通常 動的 生成さ

groovyc 明示的 生成

Java 逆生成

Java 屋必携: Jad

JadClipse 合わ 手軽

記 組 合わ

Groovy 観察

⇒Groovy 追う根性 向け

(13)

GroovyBean

class Book {

def title

private author

}

public class Book

implements GroovyObject { public Object invokeMethod() public Object getProperty() public void setProperty() public Object getTitle() public void setTitle() }

groovyc /jad

[Book.groovy] [Book.jad]

(14)

Script

def message = 'Hello' println "Say ${message}"

public class Hello extends Script{ public Hello()

public Hello(Binding context) public static transient void

main(String args[]) public Object run() }

groovyc /jad

[Hello.groovy] [Hello.jad]

一部

扱わ 記述 実行さ

(15)

Java Groovy の注意点

(16)

Groovy 基礎

表記

基曓的 Java

一行 // 複数行 /* .. */

行曒 ; ( ) 不要 良い

値指定(return) ョン 省略時 最後

構文

Java 使え

package機構

定義

制御構造 for 張さ )

演算子 代入 例外処理

生成 参照 呼び出

Groovy

簡素化 演算子 GPath

前付

範囲

扱う

(17)

Java Groovy 違い

return ョン

省略時 最後 評価

/ / public

private 無視さ

代替 場合 多い

例外

例外 処理

a==b 値性 a.eqauls(b) 意味

一性 い場合 a.is(b)

(18)

宣言

Groovy 宣言 Java

Java 可視性(修飾子 )

自動的 import

groovy.lang.*, groovy.util.*, java.lang.*, java.util.*, java.net.*, java.io.*, java.math.BigInteger,

java.math.BigDecimal

class Book {

private String title

void setTitle(String theTitle) {

title = theTitle

}

String getTitle(){

return title

} }

定型的

(boilerplate code)

(19)

GroovyBean

GroovyBean 特徴

可視性 設定さ

setter/getter 自動生成さ

bean.prop bean[prop] setter/getter 変換さ class Book {

String title }

def aBook = new Book()

aBook.setTitle('Groovy Recipes')

assert aBook.getTitle() == 'Groovy Recipes' aBook.title = 'Groovy in Action'

assert aBook.title == 'Groovy in Action' aBook['title'] = 'Groovy in Action'

assert aBook['title'] == 'Groovy in Action'

前頁 定義

(20)

張さ 文 列

表記

def name = 'Bob'

def greeting = "Hello, ${name}"

def pattern = /¥d.¥d/

def multiLineString = '''

Hello, world

My name is Groovy.'''

def multiLineGString = """

Hello, ${name}

My name is Groovy."""

String

GString

GString(¥ 不要)

複数行String

複数行GString

(21)

Java

Java

boolean, byte, short, int, long, float, double, char

特徴

Java 演算子(+,-,*,/ ) 演算

ョン (List, Map ) 格納

利用

特徴

Java 演算子(+,-,*,/ ) 演算

演算 実装 必要 (cf. BigInteger)

例外:String(Java 扱い)

ョン (List, Map ) 格納

Autoboxing (Java 5)

必要 暗黙 変換 行わ

Ease of Development 実現 .NET 影響

Groovy

(22)

数値

Groovy 数値 扱わ

演算 呼び出 変換さ

独自 演算 定義可能

def x = 1

def y = 2

assert x + y == 3

assert x.plus(y) == 3

assert x instanceof Integer

(23)

Groovy 数値

型 接尾辞

java.lang.Integer (int 範囲内 無印整数 )

例 15, 0x1234ffff

java.lang.Long L,l

java.lang.Float F,f

java.lang.Double D,d

java.math.BigInteger G,g,(int 範囲外 無印整数 )

java.math.BigDecimal G,g,( 無印 ),( 指数表記 )

例 1.23, 1.4E4, 2.8e4, 1.23g

(24)

Groovy Autoboxing

def a = 1

println a.class.name // class java.lang.Integer

a= a*99999999999999999999999999

println a.class.name // class java.math.BigInteger

println a+1 // 100000000000000000000000000

a.add(1) 直観的

記述 可能

精度 大 い方 引数

型 そ え

Ruby 自動的 型変換 行わ

階乗(**演算子) 例外 型変換 行わ

(25)

Groovy 入門編

ョン操作

制御構造

演算子 Category

•XML 操作

•Web/Web

(26)

オ とコ ョン操作

ョン

GPath

Safe dereference

張さ

List

Map

範囲 (Range 新規 )

⇒利用頻度 高い割 Java 弱い

Expando Metaclass

(27)

GPath

GPath

XPath 簡易 表記 階層 辿

obj.a.b.c => obj.getA().getB().getC()

途中 ョン 扱え

getter

出力

this.class.methods.name.grep(~/get.*/).sort()

類似 技術

XPath

/document/order/lineItem[1]

<document>要素 <order>要素 1番目 <lineItem>要素

JavaScript 参照

document.form.text1.value

現在 text1要素 内容

(28)

GPath safe dereferencing operator

safe dereferencing operator( 安全 参照演算子 ) ?.

GPath 辿 途中 null 可能性 場合 利用

Java 表記 NPE 回避

直前 null 評価 中断 結果 null

obj?.a?.b?.c => if(obj!=null) obj.getA() else null ....

(29)

List

List 言語

表記 可能

演算子([ ]) 可能

動的 張可能

def roman = ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII'] assert roman[4] == 'IV'

roman[8] = 'VIII„ roman << „IX‟

assert roman.size() == 10

def list1 = []

def list2 = [] as LinkedList

空 List(java.util.ArrayList)

List(実装 指定)

(30)

List 便利 ソッ

assert [1,[2,3]].flatten() == [1,2,3]

assert [1,2,3].intersect([4,3,1]) == [3,1] assert [3,1,2].sort() == [1,2,3]

def list = [ [1,0], [0,1,2], [2,1,0] ]

list = list.sort { a,b -> a[0] <=> b[0] } assert list = [ [0,1,2], [1,0], [2,1,0] ] def doubled = [1,2,3].collect { it*2 } assert doubled == [2,4,6]

assert [1,2,3].join(„-‟) == „1-2-3‟

(31)

Map

Map 言語

表記 可能

演算子([ ]) 可能

def http = [

100 : 'CONTINUE', 200 : 'OK',

400 : 'BAD REQUEST' ] assert http[200] == 'OK'

http[500] = 'INTERNAL SERVER ERROR' assert http.size() == 4

def map1 = [:]

def list2 = [:] as TreeMap ← new TreeMap() 等価 空 Map(java.util.HashMap)

(32)

範囲

範囲 (Range ) 言語

対応 概念 Java

表記 可能

組合 く使わ

def x = 1..10

assert x.contains(5)

assert x.contains(15) == false

assert x.from == 1

assert x.to == 10

assert x.reverse() == 10..1

def y = 1..<10

assert y.contains(10) == false

境界値 含

境界値 含 い

(33)

First Class Object 扱え

Ruby JavaScript 関数 相当

再利用や動的 有効

宣言時 環境 Lexical Scope) 保持

log = ''

(1..10).each{ log += it }

assert log == '12345678910'

map = ['a':1, 'b':2]

def doubler = {key, value -> map[key] = value * 2}

map.each(doubler)

assert map == ['a':2, 'b':4]

引数 1

it 省略可能

変数 代入可能

(34)

p [1,2,3,4,5].select {|i| i%2==0 }

Ruby

println ([1,2,3,4,5].findAll {it%2==0 } )

Groovy

1,2,3,4,5 いう数 配列 偶数

“動詞(find)+目的語(All)

Java 表記

it :

定義

(35)

意義 : Java ン 比較

Java 定型的 処理 可変 処理 多用さ

Java 再利用 単位

Swing ActionListener 実装 頻出

// Java

final JButton button = new JButton("Push me!"); button.addActionListener(new IActionListener() {

public void actionPerformed(ActionEvent event){ System.out.println(button.getText());

} } );

// Groovy

button = new JButton('Push me!') button.actionPerformed = { event ->

println button.text }

曓来必要 処理

実装

く作

曓来必要 処理

宣言時 35

(36)

Expando 動的 張可能

def obj = new Expando()

obj.hello = {println "Hello"}

obj.hello() // Hello

obj.param = "world"

println obj.param // world

ン ン 生成後 や 追加 可能

Ruby ン や

JavaScript 指向 近い機能

(37)

制御構造

Groovy 真偽

正規表現

張さ switch case

(38)

Groovy 真偽

張さ 真偽

Boolean (Java )

Matcher false true

ョン/ false 以外 true

空文 false 以外 true

数値 false 以外 true

null false 以外 true

利用可能 制御構文

if () then ... else

while () { ... }

for (elem in 範囲) { ... }, for (elem in ) { ... }

ョン.each() { ... }

switch() { case c1: ... ; break; case c2: ... ; break; deafult: ... }

(39)

制御構造 例

if (null) {

assert false } else {

assert true }

def i = 0

while (i < 10) { i++

}

assert i == 10

def clinks = 0

for (remainingGuests in 0..9) { clinks += remainingGuests }

assert clinks == (10*9)/2

def list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] for (j in list) {

assert j == list[j] }

list.each() { item ->

assert item == list[item] }

(40)

正規表現

正規表現 手軽 使う 専用 演算子

=~ : 正規表現検索演算子

正規表現 一致

評価 java.util.regex.Matcher

==~ : 正規表現 演算子

正規表現 全体一致

評価 Boolean

~ : 正規表現

扱う ~/pattern/ 書式 推奨)

評価 java.util.regex.Pattern

(41)

正規表現 例

def twister = 'she sells sea shells at the sea shore of Seychelles' assert twister =~ /s.a/

assert (twister ==~ /s.a/) == false assert twister ==~ /¥w+( ¥w+)*/ def words = twister.split(/ /)

assert words.size() == 10 switch('bear'){

case ~/..../ : assert true

case ~/b.*/ : assert true; break default : assert false

}

def animals = ['cat', 'dog', 'bear', 'wolf', 'tiger', 'elephant'] assert animals.grep(~/.../) == ['cat', 'dog']

(42)

実用的に拡張さ た switch ~ case

case 多様 条件式 表記

def x = 1.23 def result = '' switch (x) {

case "foo" : result = "found foo" case "bar" : result += "bar"; break

case [4,5,6,'inList'] : result = "list"; break case 12..30 : result = "range"; break case Integer : result = "integer"; break case Number : result = "number"; break default: result = "default"

}

println result

(43)

範囲によ 分類 (: 運賃 ) を実装

range switch case 合わ 直感的 表記

def distance = 199 def fare=0

switch (distance) { case 0..<2 :

fare = 660; break case 2..<100 :

fare = 660 + (distance - 2)*80; break case 100..<200 :

fare = 660 + (100-2)*80 + (distance - 102)*60; break default:

throw new IllegalArgumentException() }

println fare

(44)

演算子オ バ と Category

Groovy 演算子

挙動 変え

http://groovy.codehaus.org/Operator+Overloading

通常 挙動 特定 箇所 演算子

挙動 変え い場合 Category 使う

Category ( mixin)

任意個 static

use 指定 範囲内 有効

複数個 Category

可能

(45)

Category 例:日付操作

org.codehaus.groovy.runtime.TimeCategory

Date plus()/minus()

Integer getHours()/getMinutes() 追加

例:現在時刻 9 時間 5

def date = new Date()

use(org.codehaus.groovy.runtime.TimeCategory){ date = date + 9.hours + 5.minutes

}

Java ???

(46)

XML 操作

XML 方法 使え

Groovy XmlParser

XML全体

内部表現 groovy.util.Node

前空間対応

Groovy XmlSlurper

XML SAX 消費 多い

内部表現 GPathResult

前空間 無視

Java DOM

Groovy独自 提供

Java SAX/StAX JDOM 使え

(47)

def plan = new XmlParser().parse(new File('plan.xml'))

println plan.name() // plan

println plan.week[0].name() // week println plan.week[0].task[0].name() // task

println plan.week[0].task[0].„@title„ // ProjectZero

簡潔 XML Parser

<?xml version="1.0" encoding="Shift_JIS" ?>

<plan>

<week capacity="8">

<task done="1" cost="2" title="ProjectZero " />

<task done="1" cost="3" title="Groovy 作成 " />

</week>

<week capacity="8">

<task done=“0” cost=“1” title=“ 作成" />

<task done=“0” cost=“3” title=“ 実施 " />

</week>

</plan>

plan.xml

Groovy (GPath Xpath )

(48)

<tasks project=„2'>

<title>Install ProjectZero</title>

<title>Make Groovy project</title>

<title>Code it</title>

簡潔 XML Builder

def builder = new groovy.xml.MarkupBuilder();

builder.tasks([project:2]) {

title("Install ProjectZero")

title("Make Groovy project")

title("Code it")

}

println builder

Groovy

実行結果

(49)

XML 処理

XML 加工 再び XML 出力

例 以 3 ン 比較

⇒こ ン ン 意外 い

XmlParser

XmlSlurper

Dom(Groovy Dom )

詳細 参照

http://groovy.codehaus.org/Processing+XML

(50)

加工内容

<?xml version="1.0" encoding="UTF-8"?>

<shopping>

<category type="groceries">

<item> </item>

<item> </item>

</category>

<category type="supplies">

<item></item>

<item quantity="4"> </item>

</category>

<category type="present">

<item when="Aug 10">

誕生日

</item>

</category>

</shopping>

<?xml version="1.0" encoding="UTF-8"?>

<shopping>

<category type="groceries">

<item>贅沢 </item>

<item>贅沢 </item>

</category>

<category type="supplies">

<item></item>

<item when="urgent" quantity="6">

</item>

</category>

<category type="present">

<item> 誕生日</item>

<item when="Oct 15"> 誕生日

</item>

</category>

</shopping>

[shopping.xml] [shopping_modified.xml]

(51)

XmlParser

def root = new XmlParser().parse("shopping.xml")

def groceries = root.category.findAll{ it.@type == 'groceries' }.item[0] groceries.each { g -> g.value = '贅沢 ' + g.text() }

def supplies = root.category.findAll{ it.@type == 'supplies' }.item[0] supplies.findAll{ it.text() == ' ' }.each { s ->

s.@quantity = [email protected]() + 2 s.@when = 'urgent'

}

def presentCategory = root.category.find{ it.@type == 'present' } presentCategory.children().clear()

presentCategory.appendNode('item', " 誕生日")

presentCategory.appendNode('item', [when:'Oct 15'], " 誕生日") new XmlNodePrinter(new PrintWriter(System.out)).print(root)

[UpdateUsingXmlParser.groovy]

(52)

XmlSlurper

import groovy.xml.StreamingMarkupBuilder

def root = new XmlSlurper().parse('shopping.xml')

def groceries = root.category.find{ it.@type == 'groceries' }

(0..<groceries.item.size()).each { groceries.item[it] = '贅沢 ' + groceries.item[it] } def pens = root.category.find{ it.@type == 'supplies' }.item.findAll{ it.text() == ' ' } pens.each { p ->

p.@quantity = ([email protected]() + 2).toString() p.@when = 'Urgent' }

def presents = root.category.find{ it.@type == 'present' } presents.replaceNode{ node ->

category(type:'present'){ item(" 誕生日")

item(" 誕生日", when:'Oct 15') } }

def outputBuilder = new StreamingMarkupBuilder() def result = outputBuilder.bind{ mkp.yield(root) } System.out << result

[UpdateUsingXmlSlurper.groovy]

(53)

DOM + DOMCategory

import groovy.xml.dom.DOMUtil import groovy.xml.dom.DOMCategory import groovy.xml.DOMBuilder

def doc = DOMBuilder.parse(

new InputStreamReader(new FileInputStream('shopping.xml'),'UTF-8') ) def root = doc.documentElement

use(DOMCategory) {

def groceries = root.category.findAll{ it.'@type' == 'groceries' }[0].item groceries.each { g -> g.value = '豪華 ' + g.text() }

def supplies = root.category.findAll{ it.'@type' == 'supplies' }[0].item supplies.findAll{ it.text() == ' ' }.each { s ->

s['@quantity'] = s.'@quantity'.toInteger() + 2 s['@when'] = 'Urgent' }

def presents = root.category.find{ it.'@type' == 'present' } presents.item.each { presents.removeChild(it) }

presents.appendNode('item', "Mum's Birthday")

presents.appendNode('item', [when:'Oct 15'], "Monica's Birthday") }

println DOMUtil.serialize(root)

[UpdateUsingDomCategory.groovy]

(54)

Groovy DOM サポ 利用時 注意

DOMUtil.serialize()

内部 javax.xml.transform.* 利用

DOM 適用 常套手段

NoClassDefFoundError ClassCastException XSLT

わ 問題 生 場合 Groovy Xalan

(xalan.jar,serializer.jar)

DOMBuilder.parse()

Reader け付け

UTF-8

XML InputStream 経由 必要あ

英語圏 直接FileReader 多い

(55)

Web/Web

Web 利用

REST

便利 機能 普通 HTTP

XML-RPC

groovy.net.xmlrpc.*

SOAP

GroovyWS (groovyx.net.ws.*)

Web 操作 自動化

HtmlUnit ョンや

GINA 13.5.2 参照

Basic 認証

Apache Commons利用

(56)

Web 操作自動化 : Google Search

import com.gargoylesoftware.htmlunit.WebClient def client = new WebClient()

def page = client.getPage('http://www.google.com') def input = page.forms[0].getInputByName('q')

input.valueAttribute = 'Groovy' page = page.forms[0].submit()

def hits = page.anchors.grep { it.classAttribute == 'l' } [0..2]

hits.each { println it.hrefAttribute.padRight(30) + ' : ' + it.asText() } [GoogleSearch.groovy]

HtmlUnit 必要

http://htmlunit.sourceforge.net/

Google検索 結果 3

(57)

Basic 認証

import org.apache.commons.httpclient.HttpClient;

import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope;

import org.apache.commons.httpclient.methods.GetMethod; HttpClient client = new HttpClient()

client.getState().setCredentials(

new AuthScope('192.168.1.1', 80, 'RealmName'), new UsernamePasswordCredentials('user','pass') )

GetMethod get = new GetMethod('http://192.168.1.1') get.setDoAuthentication(true)

def status = client.executeMethod(get) println(status)

println(get.getResponseBodyAsString())

[BasicAuth.groovy]

Java 標準API 実現 面倒 Commons HttpClient 利用

(58)

書籍

Groovy ョン

日 ュ ョン 絶賛 売中

待望 日曓語版Groovy

Groovy-1.5 全面

Groovy 基礎 活用 幅広い話題 網羅

Grails 徹底入門

翔泳社 絶賛 売中

Groovy 章あ

Groovy曓既刊 英語版

"Groovy in Action" (Manning)

Groovy 決定版 Groovy-1.0

"Programming Groovy" (Pragmatic Bookshelf) 初心者向け 入門書 Groovy-1.5

"Groovy Recipe" (Pragmatic Bookshelf) Groovy-1.5

(59)

Let‟s get groovy!

参照

関連したドキュメント

The purpose of this study is to clarify how utilized public support system for reconstructing or repairing of damaged houses in a case of Noto Peninsula Earthquake.. Repair of

The Dubai Canal creates new public spaces along its banks and connects the historic urban enclave along Khor Dubai to the modern city, interlacing lagoons and crossing the

  If, as argued above, monetary transfers between the water utility and potential customers disconnected are not allowed, then the water utility will be required to satisfy

of “ those who don ʼ t know the administration ʼ s satoyama conservation activity ” among those who know about the NPO. Therefore, informing the residents of the administration

According to our new conception object-oriented methodology is based on the elimination of decision repetitions, that is, sorting the decisions to class hierarchy, so that the

As a module itself may be defined as an alias or a composition of other modules using paths, it might happen that module definitions end up being mutually dependent. The question is

The object of the present paper is to give applications of the Nunokawa Theorem [Proc.. Our results have some interesting examples as

[10] J. Buchmann &amp; H.C. Williams – A key exchange system based on real quadratic fields, in Advances in Cryptology – Crypto ’89, Lect. Cantor – Computing in the Jacobian of