自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

比較與分析Groovy與Java

開發(fā) 后端
本文對Groovy與java兩者之間的相同之處、不同之處及其聯(lián)系進行了總結,希望大家從中有所收獲。

Groovy與Java的比較(上)

1.支持函數(shù)式編程,不需要main函數(shù)

2.默認導入常用的包,包括:

java.io

java.math

java.net

java.util

groovy.lang

groovy.util

3.斷言不支持jvm的-ea參數(shù)進行開關

4.支持對對象進行布爾求值

支持對對象進行布爾求值

5.類不支持default作用域,且默認作用域為public

6.受檢查類型異常(Checked Exception)也可以不用捕獲

7.一些新的運算符

一些新的運算符

8.groovy中基本類型也是對象,可以直接調(diào)用對象的方法,如:

  1. assert (-12345).abs() == 12345

但浮點運算是基于BigDecimal類

  1. assert 0.25 instanceof BigDecimal
  2. assert 0.1 * 3 == 0.3
  3. assert 1.1 + 0.1 == 1.2
  4. assert 1 / 0.25 == 4

Groovy與Java的比較(中)

9.字符串的處理

String對象和java類似,但沒有character的概念,沒有迭代每個字符的方法。

使用單引號定義普通字符串,雙引號定義的字符串可以包含Groovy運算符,$符號則需要轉(zhuǎn)義("\$"),如:

  1. String name = "Ben"
  2. String greeting = "Good morning, ${name}"
  3. assert greeting == 'Good morning, Ben'
  4. String output = "The result of 2 + 2 is: ${2 + 2}"
  5. assert output == "The result of 2 + 2 is: 4"

還可以使用三個連續(xù)的"來定義多行字符串,如:

  1. String getEmailBody(String name) {
  2. return """Dear ${name},
  3. Thank you for your recent inquiry. One of our team members
  4. will process it shortly and get back to you. Some time in
  5. the next decade. Probably.
  6. Warmest and best regards,
  7. Customer Services
  8. """
  9. }

char類型的使用方法:

  1. char ch = 'D'
  2. assert ch instanceof Character
  3. String str = "Good morning Ben"
  4. str = str.replace(' ' as char, '+' as char)
  5. assert str == "Good+morning+Ben"

10.as運算符,用于沒有集成關系的類型間強制類型轉(zhuǎn)換,如:

  1. assert 543667 as String == "543667"
  2. assert 1234.compareTo("34749397" as int) < 0

可通過實現(xiàn)asType(Class) 方法來實現(xiàn)自定義的as行為,默認的方法包括:

默認的方法

11.一些集合類型的語法甜頭(Syntax sugar for lists, maps, and ranges)

從語言層面支持List\Map\Range類型,而不是通過SDK中的類

使用[]創(chuàng)建創(chuàng)建和初始化List、Map,如:

  1. List myList = [ "apple", "orange", "lemon" ]
  2. Map myMap = [ 3: "three", 6: "six", 2: "two" ]
  3. assert 3 == [ 5, 6, 7 ].size()

List\Map支持數(shù)組風格的用法

  1. List numbers = [ 5, 10, 15, 20, 25 ]
  2. assert numbers[0] == 5 //獲取List中的對象
  3. assert numbers[3] == 20
  4. assert numbers[-1] == 25 //逆序獲取List對象
  5. assert numbers[-3] == 15
  6. numbers[2] = 3 //更新List對象
  7. assert numbers[2] == 3
  8. numbers < < 30 //添加數(shù)據(jù)
  9. assert numbers[5] == 30
  10. Map items = [ "one": "apple",
  11. "two": "orange",
  12. "three": "pear",
  13. "four": "cherry" ]
  14. assert items["two"] == "orange" //從Map中獲得對象
  15. assert items["four"] == "cherry"
  16. items["one"] = "banana" //更新Map中對象
  17. assert items["one"] == "banana"
  18. items["five"] = "grape" //增加對象到中
  19. assert items["five"] == "grape"

新的類型:Range

Range實現(xiàn)了java.util.List,可以作為List使用,并擴展了包含(..)和排除(..< )運算符

  1. // an inclusive range
  2. def range = 5..8
  3. assert range.size() == 4
  4. assert range.get(2) == 7
  5. assert range[2] == 7
  6. assert range instanceof java.util.List
  7. assert range.contains(5)
  8. assert range.contains(8)
  9. // lets use an exclusive range
  10. range = 5..< 8
  11. assert range.size() == 3
  12. assert range.get(2) == 7
  13. assert range[2] == 7
  14. assert range instanceof java.util.List
  15. assert range.contains(5)
  16. assert ! range.contains(8)
  17. //get the end points of the range without using indexes
  18. def range = 1..10
  19. assert range.from == 1
  20. assert range.to == 10
  21. List fruit = [
  22. "apple",
  23. "pear",
  24. "lemon",
  25. "orange",
  26. "cherry" ]
  27. for (int i in 0..< fruit.size()) { //Iterates through an exclusive range B
  28. println "Fruit number $i is '${fruit[i]}'"
  29. }
  30. List subList = fruit[1..3] //Extracts a list slice C

12.一些省時的特性

行末的分號(;)不是必須的。在沒有分號的情況下,groovy計算一行如果是有效的表達式,則認為下一行是新的表達式,否則將聯(lián)合下一行共同作為一個表達式。分隔多行的表達式,可以用/符號,如:

  1. String fruit = "orange, apple, pear, " \
  2. + "banana, cherry, nectarine"

方法調(diào)用時的圓括號()不是必須的(但建議保留)。但在無參方法調(diào)用,或第一個參數(shù)是集合類型定義時還是必須的:

  1. println "Hello, world!"
  2. println()
  3. println([1, 2, 3, 4])

方法定義中的return語句不是必須的,沒有return的情況下,將返回方法體中最后一行的值,如下面的方法返回value+1:

int addOne(int value) { value + 1 }

Groovy與Java的比較(下)

13.語言級別的正則表達式支持

使用斜線(/)定義正則表達式,避免java中的多次轉(zhuǎn)義,如"\\\\\\w"相當于/\\\w/。

如果要作為java中的Pattern對象使用,可以使用~符號表示,如:

  1. assert ~"London" instanceof java.util.regex.Pattern
  2. assert ~/\w+/ instanceof java.util.regex.Pattern

使用=~運算符進行匹配

  1. assert "Speaking plain English" =~ /plain/

使用==~運算符進行精確匹配

  1. assert !("Speaking plain English" ==~ /plain/)
  2. assert "Speaking plain English" ==~ /.*plain.*/

捕獲分組,如:

  1. import java.util.regex.Matcher
  2. String str = "The rain in Spain falls mainly on the plain"
  3. Matcher m = str =~ /\b(\w*)ain(\w*)\b/
  4. if (m) {
  5. for (int i in 0..< m.count) {
  6. println "Found: '${m[i][0]}' - " +
  7. "prefix: '${m[i][1]}'" +
  8. ", suffix: '${m[i][2]}'"
  9. }
  10. }

輸出:

  1. Found: 'rain' - prefix: 'r', suffix: ''
  2. Found: 'Spain' - prefix: 'Sp', suffix: ''
  3. Found: 'mainly' - prefix: 'm', suffix: 'ly'
  4. Found: 'plain' - prefix: 'pl', suffix: ''

14.簡化的javabean

直接使用“.屬性名”的方法代替getter,如:

  1. Date now = new Date()
  2. println "Current time in milliseconds: ${ now.time }"
  3. now.time = 103467843L
  4. assert now.time == 103467843L

屬性定義不需要setter/getter。未指定作用域的屬性,groovy自動認為是private并生為其成setter/getter,也可以根據(jù)需要進行覆寫。如下除了最后一個字段,都是屬性:

  1. class MyProperties {
  2. static String classVar
  3. final String constant = "constant"
  4. String name
  5. public String publicField
  6. private String privateField
  7. }

簡化bean的初始化,可以使用Map進行初始化,或鍵值對的方法,如

  1. DateFormat format = new SimpleDateFormat(
  2. lenient: false,
  3. numberFormat: NumberFormat.getIntegerInstance(),
  4. timeZone: TimeZone.getTimeZone("EST"))

可以使用屬性的方式讀取map:

  1. Map values = [ fred: 1, peter: 5, glen: 42 ]
  2. assert values.fred == 1
  3. values.peter = 10
  4. assert values.peter == 10

注:groovy將map的key作為字符串處理,除非是數(shù)字或者用圓括號包含。這里的fred就是字符串"fred",但引號不是必須的,只有在key包含空格、句點或其他不能作為Groovy標示符的字符存在時才需要。如果需要使用一個變量的值作為key,則使用圓括號,如 [ (fred): 1 ]。

15.groovy不具備的java特性

不能用單引號定義字符類型,但可以使用as運算符將一個字母的字符串轉(zhuǎn)換為字符類型

for循環(huán)中不能用逗號分隔多個運算符,如下面的代碼是不允許的:

  1. for (int i = 0, j = 0; i < 10; i++, j++) { ... }

不支持DO...WHILE循環(huán),但可以使用while...for運算代替

不支持內(nèi)部類和匿名類,但支持閉包和在一個文件中定義多個類

16.groovy的重要特性——閉包:

可以看作一個匿名方法定義,可以賦予給一個變量名、作為參數(shù)傳遞給方法調(diào)用、或者被方法返回。也可以想象為只有一個方法定義的匿名類。

閉包的語法{ < arguments> -> < body> },如:

  1. List fruit = [ "apple", "Orange", "Avocado", "pear", "cherry" ]
  2. fruit.sort { String a, String b -> a.compareToIgnoreCase(b) }
  3. println "Sorted fruit: ${fruit}"

注:sort方法只有一個閉包類型的參數(shù),省略了圓括號;閉包中使用了默認的return值

當沒有參數(shù)傳入時,仍然需要保留箭頭的存在{-> ... }

只有一個參數(shù)傳入時,可以省略箭頭,隱式的創(chuàng)建一個it參數(shù),引用當前對象,如:

  1. [ "apple", "pear", "cherry" ].each { println it }

可以將閉包賦予一個變量,如

  1. Closure comparator = { String a, String b ->
  2. a.compareToIgnoreCase(b)
  3. }
  4. List fruit = [ "apple", "Orange", "Avocado", "pear", "cherry" ]
  5. fruit.sort(comparator)
  6. println "Sorted fruit: ${fruit}"
  7. assert comparator("banana", "Lemon") < 0

只有一個參數(shù)的閉包,可以不傳入?yún)?shù),運行時隱式的傳入null參數(shù)

當閉包是一個方法的最后一個參數(shù)時,可以寫在圓括號外面,如:

  1. List list = [ 1, 3, 5, 6 ]
  2. list.inject(0, { runningTotal, value -> runningTotal + value })

可以這樣寫:

  1. assert 15 == list.inject(0) { runningTotal, value -> runningTotal + value }

便于閉包中具有多行時代碼更加清晰

不要濫用閉包。當閉包作為一個屬性時,不要在子類中覆寫,實在需要這樣做,使用方法。使用閉包也無法利用java中很多AOP框架的特性

17.groovy的重要特性——動態(tài)編程

動態(tài)的使用屬性,如下的java代碼:

  1. public void sortPeopleByGivenName(List< Person> personList) {
  2. Collections.sort(personList, new Comparator< Person>() {
  3. public int compare(Person p1, Person p2) {
  4. return p1.getFamilyName().compareTo(p2.getFamilyName());
  5. }
  6. } ) ;
  7. }

可使用下面的代替,當需要使用其他字段比較時,不需要修改代碼

  1. def sortPeople(people, property) {
  2. people.sort { p1, p2 -> p1."${property}" < => p2."${property}" }
  3. }

將一個String作為屬性或方法名進行調(diào)用,如:

  1. peopleList.sort()
  2. peopleList."sort"()

動態(tài)類型(duck typing:"if it walks like a duck and talks like a duck, it’s probably a duck):運行期解析對象的屬性和方法,允許在運行時增加對象的屬性和方法而不修改源代碼,因此可能出現(xiàn)調(diào)用未定義方法的情況。

動態(tài)編程帶來的危險:

編譯器不能檢查到類型錯誤、方法或?qū)傩缘腻e誤調(diào)用,應該養(yǎng)成編寫測試的習慣

難以調(diào)試,使用“單步跳入(step into)”經(jīng)常進入一些反射中,使用“運行到光標處(run to cursor)”代替

動態(tài)的類型定義使代碼難以閱讀,使用良好的命名、注釋,盡量明確定義變量類型,便于IDE檢測ht potential type errors in the call潛在的錯誤。

18.Groovy JDK中的增強

Collection/Array/String具有size()方法

Collection/Array/String具有each(closure)方法,方便的進行遍歷

Collection/Array/String具有find(closure)、findAll(closure)方法,find返回第一個符合條件的對象,findAll返回所有符合條件對象列表,如:

  1. def glen = personList.find { it.firstName == "Glen" }

Collection/Array/String具有collect(closure)方法,對集合中每個對象執(zhí)行一段方法后,返回結果集,如:

  1. def names = [ "Glen", "Peter", "Alice", "Graham", "Fiona" ]
  2. assert [ 4, 5, 5, 6, 5 ] == names.collect { it.size() }

Collection/Array/String具有sort(closure)方法,包括:

一個參數(shù)的閉包,如:

  1. def names = [ "Glen", "Peter", "Ann", "Graham", "Veronica" ]
  2. def sortedNames = names.sort { it.size() }
  3. assert [ "Ann", "Glen", "Peter", "Graham", "Veronica" ] == sortedNames

兩個參數(shù)的閉包,如:

  1. def names = [ "Glen", "Peter", "Ann", "Graham", "Veronica" ]
  2. def sortedNames = names.sort { name1, name2 ->
  3. name1.size() < => name2.size()
  4. }
  5. assert [ "Ann", "Glen", "Peter", "Graham", "Veronica" ] == sortedNames

Collection/Array具有join(String)方法

  1. def names = [ "Glen", "Peter", "Alice", "Fiona" ]
  2. assert "Glen, Peter, Alice, Fiona" == names.join(", ")

File.text屬性讀取文件內(nèi)容作為字符串返回

File.size()方法返回文件的byte值,相當于File.length()方法

File.withWriter(closure)方法,從文件創(chuàng)建一個Writer對象傳給閉包,閉包執(zhí)行完畢后,依賴的輸出流自動安全關閉。另外還有若干with...方法查看文檔

Matcher.count返回相應Matcher的匹配數(shù)量

Number.abs()方法,對數(shù)字求絕對值

Number.times(closure)執(zhí)行n次閉包,將當前執(zhí)行的次數(shù)作為參數(shù)傳給閉包

19.XML的處理

示例的XML:

  1. < root>
  2. < item qty="10">
  3. < name>Orange< /name>
  4. < type>Fruit< /type>
  5. < /item>
  6. < item qty="6">
  7. < name>Apple< /name>
  8. < type>Fruit< /type>
  9. < /item>
  10. < item qty="2">
  11. < name>Chair< /name>
  12. < type>Furniture< /type>
  13. < /item>
  14. < /root>

處理程序

  1. import groovy.xml.MarkupBuilder
  2. import groovy.util.XmlSlurper
  3. def file = new File("test.xml")
  4. def objs = [
  5. [ quantity: 10, name: "Orange", type: "Fruit" ],
  6. [ quantity: 6, name: "Apple", type: "Fruit" ],
  7. [ quantity: 2, name: "Chair", type: "Furniture" ] ]
  8. def b = new MarkupBuilder(new FileWriter(file)) 創(chuàng)建MarkupBuilder對象
  9. b.root {
  10. 動態(tài)調(diào)用root方法,但builder對象并沒有該方法,把它作為一個新的XML對象的根節(jié)點,并且把方法名作為根節(jié)點名稱
  11. objs.each { o ->
  12. item(qty: o.quantity) {
  13. name(o.name)
  14. type(o.type)
  15. }
  16. }
  17. }
  18. 遍歷集合,創(chuàng)建節(jié)點,其中item/name/type也是動態(tài)的方法,以方法名作為節(jié)點名,方法參數(shù)作為節(jié)點的屬性
  19. def xml = new XmlSlurper().parse(file)
  20. 使用XmlSlurper對象解析內(nèi)存中的XML文件
  21. assert xml.item.size() == 3
  22. assert xml.item[0].name == "Orange"
  23. assert xml.item[0].@qty == "10"
  24. 使用動態(tài)的屬性名讀取XML節(jié)點
  25. 使用@字符讀取節(jié)點屬性
  26. println "Fruits: ${xml.item.findAll {it.type == 'Fruit'}*.name }"
  27. println "Total: ${xml.item.@qty.list().sum {it.toInteger()} }"

20.最佳實踐

使用地道的Groovy語法:盡可能使用groovy中簡化后的語法風格,減少代碼量

實驗:使用groovy console或shell可以方便的實驗groovy代碼

盡可能使用方法,而不是閉包。方法易于理解,也利于和java交互

在方法簽名中盡可能的使用確定的類型,便于代碼閱讀和IDE的錯誤檢測。在使用動態(tài)類型時要有清晰完善的文檔注釋

【編輯推薦】

  1. 多核時代考驗Java代碼編寫習慣
  2. JSR通過JavaEE 6依賴注入標準 各方觀點不一
  3. Sun發(fā)布JDK 7早期預覽版 JVM性能大幅提升
  4. 來自一年前的預測:Java平臺與死亡相去甚遠
  5. Java新型垃圾回收器G1深入探索
責任編輯:book05 來源: popoer
相關推薦

2017-04-27 10:38:28

排序算法比較分析

2012-07-02 14:47:38

HTML5

2009-08-03 10:44:51

Groovy 1.7Groovy

2012-10-11 10:51:39

開源IaaS云

2011-09-22 13:49:44

XML基準測試

2013-12-10 23:06:58

開源云平臺云計算

2009-07-07 17:23:08

Java Servle

2017-03-07 09:05:05

JavaScriptJavaPHP

2018-11-01 09:14:42

CNNRNN神經(jīng)網(wǎng)絡

2023-01-10 08:04:31

2010-07-14 10:15:31

2009-09-14 18:39:41

MCSE與CCNA

2020-08-11 10:05:16

Qlik SenseTableau數(shù)據(jù)分析

2010-05-12 11:24:16

2023-02-07 09:17:19

Java注解原理

2010-08-23 14:44:06

思科

2009-07-03 12:48:24

Java Servle

2009-08-07 10:27:45

Eclipse和Net

2010-03-11 10:51:19

Python編程語言

2009-07-14 16:30:41

Swing與SWT
點贊
收藏

51CTO技術棧公眾號