成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Groovy 2.0新特性之:靜態(tài)類型檢查

開發(fā) 后端
Groovy 2.0 剛剛發(fā)布,其中一項(xiàng)最大的改進(jìn)就是支持靜態(tài)類型檢查。今天我們將對(duì)這個(gè)新特性進(jìn)行全方位的介紹。

Groovy 2.0 剛剛發(fā)布,其中一項(xiàng)最大的改進(jìn)就是支持靜態(tài)類型檢查。今天我們將對(duì)這個(gè)新特性進(jìn)行全方位的介紹。

靜態(tài)類型檢查

Groovy 天生就是一個(gè)動(dòng)態(tài)編程語言,它經(jīng)常被當(dāng)作是 Java 腳本語言,或者是“更好的 Java”。很多 Java 開發(fā)者經(jīng)常將 Groovy 嵌入到 Java 程序中做為擴(kuò)展語言來使用,更簡單的描述業(yè)務(wù)規(guī)則,將來為不同的客戶定制應(yīng)用等等。對(duì)這樣一個(gè)面向 Java 的用例,開發(fā)者不需要語言提供的所有動(dòng)態(tài)特性,他們經(jīng)常希望 Groovy 也提供一個(gè)類似 javac 的編譯器,例如在發(fā)生一些錯(cuò)誤的變量和方法名錯(cuò)誤或者錯(cuò)誤的類型賦值時(shí)就可以在編譯時(shí)就知道錯(cuò)誤,而不是運(yùn)行時(shí)才報(bào)錯(cuò)。這就是為什么 Groovy 2.0 提供了靜態(tài)類型檢查功能的原因。

發(fā)現(xiàn)明顯的錯(cuò)別字

靜態(tài)類型檢測器使用了 Groovy 已有強(qiáng)大的 AST (抽象語法樹) 轉(zhuǎn)換機(jī)制,如果你對(duì)這個(gè)機(jī)制不熟悉,你就把它當(dāng)作一個(gè)可選的通過注解進(jìn)行觸發(fā)的編譯器插件。這是一個(gè)可選的特性,可用可不用。要觸發(fā)靜態(tài)類型檢查,只需要在方法上使用@TypeChecked 注解即可。讓我們來看一個(gè)簡單的例子:

 

  1. import groovy.transform.TypeChecked  
  2.  
  3. void someMethod() {}  
  4.  
  5. @TypeChecked 
  6. void test() {  
  7.     // compilation error:  
  8.     // cannot find matching method sommeeMethod()  
  9.     sommeeMethod()  
  10.  
  11.     def name = "oschina" 
  12.  
  13.     // compilation error:  
  14.     // the variable naaammme is undeclared  
  15.     println naaammme  

 

我們使用了 @TypeChecked 對(duì) test() 方法進(jìn)行注解,這讓 Groovy 編譯器在編譯期間運(yùn)行靜態(tài)類型檢查來檢查指定的方法。當(dāng)我們?cè)噲D用明顯錯(cuò)誤的方法來調(diào)用 someMethod() 時(shí),編譯器將會(huì)拋出兩個(gè)編譯錯(cuò)誤信息表明方法和變量為定義

檢查賦值和返回值

靜態(tài)類型檢查還能驗(yàn)證返回值和變量賦值是否匹配:

 

  1. import groovy.transform.TypeChecked  
  2.  
  3. @TypeChecked 
  4. Date test() {  
  5.     // compilation error:  
  6.     // cannot assign value of Date   
  7.     // to variable of type int  
  8.     int object = new Date()  
  9.  
  10.     String[] letters = ['o''s''c']  
  11.     // compilation error:  
  12.     // cannot assign value of type String   
  13.     // to variable of type Date  
  14.     Date aDateVariable = letters[0]  
  15.  
  16.     // compilation error:  
  17.     // cannot return value of type String   
  18.     // on method returning type Date  
  19.     return "today" 

 

在這個(gè)例子中,編譯器將告訴你不能將 Date 值賦值個(gè) int 變量,你也不能返回一個(gè) String,因?yàn)榉椒ㄒ呀?jīng)要求是返回 Date 類型數(shù)據(jù)。代碼中間的編譯錯(cuò)誤信息也很有意思,不僅是說明了錯(cuò)誤的賦值,還給出了類型推斷,因?yàn)轭愋蜋z測器知道 letters[0] 的類型是 String。

類型推斷 type inference

因?yàn)樘岬搅祟愋屯茢啵屛覀儊砜纯雌渌囊恍┣闆r,我們說過類型檢測器會(huì)檢查返回類型和值:

 

  1. import groovy.transform.TypeChecked  
  2.  
  3. @TypeChecked 
  4. int method() {  
  5.     if (true) {  
  6.         // compilation error:  
  7.         // cannot return value of type String  
  8.         // on method returning type int  
  9.         'String' 
  10.     } else {  
  11.         42 
  12.     }  

 

指定了方法必須返回 int 類型值后,類型檢查器將會(huì)檢查各種條件判斷分支的結(jié)構(gòu),包括 if/elese、try/catch、switch/case 等。在上面的例子中,如果 if 分支中返回字符串而不是 int,編譯器就會(huì)報(bào)錯(cuò)。

自動(dòng)類型轉(zhuǎn)換

靜態(tài)類型檢查器并不會(huì)對(duì) Groovy 支持的自動(dòng)類型轉(zhuǎn)換報(bào)告錯(cuò)誤,例如對(duì)于返回 String, boolean 或 Class 的方法,Groovy 會(huì)自動(dòng)將返回值轉(zhuǎn)成相應(yīng)的類型:

 

  1. import groovy.transform.TypeChecked  
  2.  
  3. @TypeChecked 
  4. boolean booleanMethod() {  
  5.     "non empty strings are evaluated to true" 
  6. }  
  7.  
  8. assert booleanMethod() == true 
  9.  
  10. @TypeChecked 
  11. String stringMethod() {  
  12.     // StringBuilder converted to String calling toString()  
  13.     new StringBuilder() << "non empty string" 
  14. }  
  15.  
  16. assert stringMethod() instanceof String  
  17.  
  18. @TypeChecked 
  19. Class classMethod() {  
  20.     // the java.util.List class will be returned  
  21.     "java.util.List" 
  22. }  
  23.  
  24. assert classMethod() == List 

 

而且靜態(tài)類型檢查器在類型推斷方面也足夠聰明:

 

  1. import groovy.transform.TypeChecked  
  2.  
  3. @TypeChecked 
  4. void method() {  
  5.     def name = " oschina.net " 
  6.  
  7.     // String type inferred (even inside GString)  
  8.     println "NAME = ${name.toUpperCase()}" 
  9.  
  10.     // Groovy GDK method support  
  11.     // (GDK operator overloading too)  
  12.     println name.trim()  
  13.  
  14.     int[] numbers = [123]  
  15.     // Element n is an int  
  16.     for (int n in numbers) {  
  17.         println   
  18.     }  

 

雖然變量 name 使用 def 進(jìn)行定義,但類型檢查器知道它的類型是 String. 因此當(dāng)調(diào)用 ${name.toUpperCase()} 時(shí),編譯器知道在調(diào)用 String 的 toUpperCase() 方法和下面的 trim() 方法。當(dāng)對(duì) int 數(shù)組進(jìn)行迭代時(shí),它也能理解數(shù)組的元素類型是 int.

混合動(dòng)態(tài)特性和靜態(tài)類型的方法

你必須牢記于心是:靜態(tài)類型檢查限制了你可以在 Groovy 使用的方法。大部分運(yùn)行時(shí)動(dòng)態(tài)特性是不被允許的,因?yàn)樗麄儫o法在編譯時(shí)進(jìn)行類型檢查。例如不允許在運(yùn)行時(shí)通過類型的元數(shù)據(jù)類(metaclasses)來添加新方法。但當(dāng)你需要使用一些例如 Groovy 的 builders 這樣的動(dòng)態(tài)特性時(shí),如果你愿意,你還是可以選擇靜態(tài)類型檢查。

@TypeChecked 注解可放在方法級(jí)別或者是類級(jí)別使用。如果你想對(duì)整個(gè)類進(jìn)行類型檢查,直接在類級(jí)別上放置這個(gè)注解即可,否則就在某些方法上進(jìn)行注解。你也可以使用 @TypeChecked(TypeCheckingMode.SKIP) 或者是 @TypeChecked(SKIP) 來指定整個(gè)類進(jìn)行類型檢查除了某個(gè)方法。使用 @TypeChecked(SKIP) 必須靜態(tài)引入對(duì)應(yīng)的枚舉類型。下面代碼可以用來演示這個(gè)特性,其中 greeting() 方法是需要檢查的,而 generateMarkup() 方法則不用:

 

  1. import groovy.transform.TypeChecked  
  2. import groovy.xml.MarkupBuilder  
  3.  
  4. // this method and its code are type checked  
  5. @TypeChecked 
  6. String greeting(String name) {  
  7.     generateMarkup(name.toUpperCase())  
  8. }  
  9.  
  10. // this method isn't type checked  
  11. // and you can use dynamic features like the markup builder  
  12. String generateMarkup(String name) {  
  13.     def sw =new StringWriter()  
  14.     new MarkupBuilder(sw).html {  
  15.         body {  
  16.             div name  
  17.         }  
  18.     }  
  19.     sw.toString()  
  20. }  
  21.  
  22. assert greeting("Cédric").contains("<div>CÉDRIC</div>"

 

類型推斷和 instanceof 檢查

目前的 Java 并不支持一般的類型推斷,導(dǎo)致今天很多地方的代碼往往是相當(dāng)冗長,而且樣板結(jié)構(gòu)混亂。這掩蓋了代碼的實(shí)際用途,而且如果沒有強(qiáng)大的 IDE 支持的話代碼會(huì)很難寫。于是就有了 instanceof 檢查:你經(jīng)常會(huì)在 if 條件判斷語句中使用 instanceof 判斷。而在 if 語句結(jié)束后,你還是必須手工對(duì)變量進(jìn)行強(qiáng)行類型轉(zhuǎn)換。而有了 Groovy 全新的類型檢查模式,你可以完全避免這種情況出現(xiàn):

 

  1. import groovy.transform.TypeChecked  
  2. import groovy.xml.MarkupBuilder  
  3.  
  4. @TypeChecked 
  5. String test(Object val) {  
  6.     if (val instanceof String) {  
  7.         // unlike Java:   
  8.         // return ((String)val).toUpperCase()  
  9.         val.toUpperCase()  
  10.     } else if (val instanceof Number) {  
  11.         // unlike Java:   
  12.         // return ((Number)val).intValue().multiply(2)  
  13.         val.intValue() * 2 
  14.     }  
  15. }  
  16.  
  17. assert test('abc') == 'ABC' 
  18. assert test(123) == '246' 

 

上述例子中,靜態(tài)類型檢查器知道 val 參數(shù)在 if 塊中是 String 類型,而在 else if 塊中是 Number 類型,無需再做任何手工類型轉(zhuǎn)換。

最低上限 Lowest Upper Bound

靜態(tài)類型檢測器比一般理解的對(duì)象類型診斷要更深入一些,請(qǐng)看如下代碼:

 

  1. import groovy.transform.TypeChecked  
  2.  
  3. // inferred return type:  
  4. // a list of numbers which are comparable and serializable  
  5. @TypeChecked test() {  
  6.     // an integer and a BigDecimal  
  7.     return [12343.14]  

 

在這個(gè)例子中,我們返回了數(shù)值列表,包括 Integer 和 BigDecimal. 但靜態(tài)類型檢查器計(jì)算了一個(gè)最低的上限,實(shí)際上是一組可序列化(Serializable)和可比較(Comparable)的數(shù)值。而 Java 是不可能表示這種類型的,但如果我們使用一些交集運(yùn)算,那看起來就應(yīng)該是 List<Number & Serializable & Comparable>.

不同對(duì)象類型的變量 Flow typing

雖然這可能不是一個(gè)好的方法,但有時(shí)候開發(fā)者會(huì)使用一些無類型的變量來存儲(chǔ)不同類型的值,例如:

 

  1. import groovy.transform.TypeChecked  
  2.  
  3. @TypeChecked test() {  
  4.     def var = 123             // inferred type is int  
  5.     var = "123"               // assign var with a String  
  6.  
  7.     println var.toInteger()   // no problem, no need to cast  
  8.  
  9.     var = 123 
  10.     println var.toUpperCase() // error, var is int!  

 

上面代碼中 var 變量一開始是 int 類型,后來又賦值了字符串,“flow typing”算法可以理解賦值的順序,并指導(dǎo) var 當(dāng)前是字符串類型,這樣調(diào)用 Groovy 為 String 增加的 toInteger() 方法就沒問題。緊接著又賦值整數(shù)給 var 變量,但現(xiàn)在如果再次調(diào)用 toUpperCase() 就會(huì)報(bào)出編譯錯(cuò)誤。

還有另外一些關(guān)于 “flow typing” 算法的特殊情況,當(dāng)某個(gè)變量在一個(gè)閉包中被共享該會(huì)是怎么樣的一種情況呢?

 

  1. import groovy.transform.TypeChecked  
  2.  
  3. @TypeChecked test() {  
  4.     def var = "abc" 
  5.     def cl = {  
  6.         if (new Random().nextBoolean()) var = new Date()  
  7.     }  
  8.     cl()  
  9.     var.toUpperCase() // compilation error!  

 

var 本地變量先賦值了一個(gè)字符串,但是在閉包中會(huì)在一些隨機(jī)的情況下被賦值為日期類型數(shù)值。一般情況下這種只能在運(yùn)行時(shí)才能報(bào)錯(cuò),因?yàn)檫@種錯(cuò)誤是隨機(jī)發(fā)生的。因此在編譯時(shí),編譯器是沒有機(jī)會(huì)知道 var 變量是字符串還是日期,這就是為什么編譯器無法得知錯(cuò)誤的原因。盡管這個(gè)例子有點(diǎn)做作,但還有更有趣的情況:

 

  1. import groovy.transform.TypeChecked  
  2.  
  3. class A           { void foo() {} }  
  4. class B extends A { void bar() {} }  
  5.  
  6. @TypeChecked test() {  
  7.     def var = new A()  
  8.     def cl = { var = new B() }  
  9.     cl()  
  10.     // var is at least an instance of A  
  11.     // so we are allowed to call method foo()  
  12.     var.foo()  

 

在 test() 方法中,var 先被賦值為 A 的實(shí)例,緊接著在閉包中被賦值為 B 的實(shí)例,然后調(diào)用這個(gè)閉包方法,因此我們至少可以診斷 var 最后的類型是 A。

Groovy 編譯器的所有這些檢查都是在編譯時(shí)就完成了,但生成的字節(jié)碼還是跟一些動(dòng)態(tài)代碼一樣,在行為上沒有任何改變。

原文鏈接:http://www.oschina.net/question/12_59498

責(zé)任編輯:林師授 來源: OSCHINA
相關(guān)推薦

2012-07-12 11:23:07

GroovyJVM

2023-01-05 08:09:27

GroovyDSL?

2023-01-06 08:06:52

Groovy類型擴(kuò)展

2009-06-15 16:15:37

Spring2.0新特

2012-03-14 12:29:55

JavaPlay Framwo

2013-02-25 14:02:07

RubyWeb

2009-06-18 15:40:07

Spring Batc

2009-05-25 15:42:03

Visual StudC#

2009-07-30 14:55:43

ASP.NET 2.0

2018-05-30 15:10:24

Spring BootList類型

2009-11-04 14:17:34

ADO.NET 2.0

2011-09-30 14:15:10

Sencha ToucSencha Touc

2013-02-26 09:36:57

RubyRuby 2.0

2015-06-23 15:48:41

Swift 2.0iOS9

2018-06-06 14:30:38

Spring BootApplication事件

2012-07-02 10:40:24

GroovyJavaJVM

2009-07-03 17:40:35

JSP2.0

2009-08-18 09:17:01

JavaScript2

2021-07-08 18:10:03

2011-05-20 09:59:42

JDK7
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 在线观看成人小视频 | 激情欧美一区二区三区中文字幕 | 中文字幕 亚洲一区 | 亚洲精品久久久久久宅男 | 日朝毛片 | 一级黄色片在线免费观看 | 亚洲第一视频网站 | 91精品国产综合久久久久蜜臀 | 一色一黄视频 | 尤物在线精品视频 | 欧美激情精品久久久久久免费 | 黄色一级电影免费观看 | 久久久久久91 | 日韩中文在线视频 | 免费成人毛片 | 青青草原综合久久大伊人精品 | 丁香婷婷在线视频 | 亚洲国产一区二区视频 | 亚洲在线一区二区 | 伊人网站在线观看 | 日本天天操 | 911网站大全在线观看 | 精品一区在线 | 成人国产网站 | av免费网站在线观看 | 午夜电影日韩 | 国产一区二区精品 | 日本成人毛片 | av在线播放一区二区 | 五月婷婷视频 | 天天碰日日操 | www操操 | 久久久中文 | 欧美日韩视频在线第一区 | 99pao成人国产永久免费视频 | 亚洲人成在线播放 | 国产色99 | 一区二区在线 | 蜜月aⅴ国产精品 | 国产精品欧美一区二区 | 欧美二区在线 |