Groovy如何帮助JavaFX:别了,纯粹的Java代码?

译文
开发 开发工具
今年的JavaOne大会上,JavaFX再次露了一把脸,而同时活跃在大会上的还有Groovy,Scala等围绕着Java平台的语言。大会中的一个展示应用是由JavaFX和Groovy合作完成的,本文作者在观展之后写下了这篇文章,认为纯粹的Java代码时代即将终结。虽然作者对于JavaFX与Java的差别似乎有些理解上的偏差,但这并不妨碍开发者们对于这篇文章的关注,以及对Java平台上语言的发展趋势之展望。

【51CTO快译】在众多为试用者所熟知的JavaFX酷例应用当中,JavaFX天气应用程序是其中之一,现在它已经捆绑进NetBeans IDE 6.5.1/JavaFX 1.2 绑定包了。简而言之,它连接到一个气象服务那里,然后利用一个令人印象深刻的JavaFX GUI选定城市的天气结果:

JavaFX天气应用

在周三JavaOne上(有关JavaOne 2009,可参考51CTO之前的JavaOne 2009全线报导)举行的一个主题为“JavaFX编程语言+Groovy=美+生产力”的技术研讨会上,Dierk König 展示了若干强大的Groovy与 JavaFX互动的方式。以下是其中一种方式的概要,含全部代码及结果。这真的令人印象深刻,并让Dierk在会上演示时赢得了来自听众的一轮掌声。

JavaFX天气应用使用这个海量Java类创建了如上的GUI,用以连接到Yahoo的气象服务。Java类连接到的完整的RSS种子如下所示:

  1. <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
  2. <rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"> 
  3.  
  4.     <channel> 
  5.  
  6.         <title>Yahoo! Weather - Prague, EZ</title> 
  7.         <link>http://us.rd.yahoo.com/dailynews/rss/weather/Prague__EZ/*http://weather.yahoo.com/forecast/EZXX0012_f.html</link> 
  8.         <description>Yahoo! Weather for Prague, EZ</description> 
  9.         <language>en-us</language> 
  10.         <lastBuildDate>Fri, 05 Jun 2009 8:00 pm CEST</lastBuildDate> 
  11.         <ttl>60</ttl> 
  12.  
  13.         <yweather:location city="Prague" region=""   country="EZ"/> 
  14.         <yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/> 
  15.         <yweather:wind chill="54"   direction="60"   speed="3" /> 
  16.         <yweather:atmosphere humidity="58"  visibility="6.21"  pressure="29.8"  rising="0" /> 
  17.         <yweather:astronomy sunrise="4:56 am"   sunset="9:06 pm"/> 
  18.  
  19.         <image> 
  20.             <title>Yahoo! Weather</title> 
  21.             <width>142</width> 
  22.             <height>18</height> 
  23.             <link>http://weather.yahoo.com</link> 
  24.             <url>http://l.yimg.com/a/i/us/nws/th/main_142b.gif</url> 
  25.         </image> 
  26.  
  27.         <item> 
  28.  
  29.             <title>Conditions for Prague, EZ at 8:00 pm CEST</title> 
  30.             <geo:lat>50.1</geo:lat> 
  31.             <geo:long>14.28</geo:long> 
  32.             <link>http://us.rd.yahoo.com/dailynews/rss/weather/Prague__EZ/*http://weather.yahoo.com/forecast/EZXX0012_f.html</link> 
  33.             <pubDate>Fri, 05 Jun 2009 8:00 pm CEST</pubDate> 
  34.             <yweather:condition  text="Partly Cloudy"  code="30"  temp="54"  date="Fri, 05 Jun 2009 8:00 pm CEST" /> 
  35.             <description><![CDATA[  
  36. <img src="http://l.yimg.com/a/i/us/we/52/30.gif"/>  
  37. <b>Current Conditions:</b>  
  38. Partly Cloudy, 54 F  
  39. <b>Forecast:</b>  
  40. Fri - Partly Cloudy. High: 58 Low: 42  
  41. Sat - PM Rain. High: 58 Low: 49  
  42. <a href="http://us.rd.yahoo.com/dailynews/rss/weather/Prague__EZ/*http://weather.yahoo.com/forecast/EZXX0012_f.html">Full Forecast at Yahoo! Weather</a>(provided by The Weather Channel)  
  43.  
  44. ]]> 
  45.             </description> 
  46.             <yweather:forecast day="Fri" date="5 Jun 2009" low="42" high="58" text="Partly Cloudy" code="29" /> 
  47.             <yweather:forecast day="Sat" date="6 Jun 2009" low="49" high="58" text="PM Rain" code="12" /> 
  48.             <guid isPermaLink="false">EZXX0012_2009_06_05_20_00_CEST</guid> 
  49.  
  50.         </item> 
  51.  
  52.     </channel> 
  53.  
  54. </rss> 

现在,不管你有没有听说过“Groovy”,你都要考虑一下“老土的工作”(译注:grunt work,Groovy的谐音)。这正是Groovy尤其擅长的地方。一个相关的有力案例是web服务。还有,其HTML和XML的解析。因此,一旦你需要在Java应用中与web服务交互,最应该考虑的助手显然就是Groovy了。
看一下上面的RSS然后看看下面Groovy代码的11行,以下是相关代码:

  1. def channel = new XmlParser().parse(url).channel 

这一行给了你上面的RSS种子的“channel”元素!了不起,是不是?而从那儿开始,下面的Groovy脚本对RSS种子进行解析,确切地识别出那些JavaFX GUI感兴趣的部分,然后用了大约20行,产生出的结果,跟通常约需250行才能做出来的一模一样。

看看下面的Groovy代码段,跟上面的RSS种子对比一下,来了解它是如何工作的。注意,这甚至还不是代码段!这就是Groovy web service类的全部了。这简直就是酷毙了,尤其是再把它跟原来的丑陋代码比对过之后。

  1. package weatherfx.service  
  2.  
  3. class YahooWeatherServiceG {  
  4.     static YW = new groovy.xml.Namespace("http://xml.weather.yahoo.com/ns/rss/1.0")  
  5.  
  6.     def forecasts  
  7.       
  8.     YahooWeatherServiceG(String code, boolean celsius) {  
  9.         def url = "http://weather.yahooapis.com/forecastrss?u=f&p=$code" 
  10.         println url.toURL().text  
  11.         def channel = new XmlParser().parse(url).channel  
  12.         cityName = channel[YW.location].@city 
  13.         def wind = channel[YW.wind].first()  
  14.         windSpeed = wind.@speed.toInteger()  
  15.         windDirection = wind.@direction.toInteger()  
  16.         def cond = channel.item[YW.condition].first()  
  17.         temp = cond.@temp.toInteger()  
  18.         forecasts = channel.item[YW.forecast]  
  19.     }  
  20.  
  21.     String cityName   
  22.     int temp  
  23.     int windSpeed  
  24.     int windDirection  
  25.  
  26.     int getConditionCode(int day=0) { forecasts[day].@code.toInteger() }  
  27.     int getLowsTemp     (int day=0) { forecasts[day].@low.toInteger()  }  
  28.     int getHighsTemp    (int day=0) { forecasts[day].@high.toInteger() }  
  29. }  

现在,停下来想象一下,上述代码跟其原始纯粹的Java代码相比起来,(a)测试和(b)维护是不是要简单、高效得多,且不易出错?

不过,目前还没有一个JavaFX/Groovy的交叉编译器。因此,怎样去把你的Java web service代码替换为上面的Groovy代码呢?首先创建一个独立的工程来建立你的Groovy web service。然后,将该工程添加进你的JavaFX应用的classpath。接着,将你的JavaFX应用中的两三个指向原始Java类的引用替换为指向Groovy class (经编译后现在已是Java类) 。

上述这一段做完之后如下图所示:

改写结果 

然后运行JavaFX应用,你将得到跟先前一样的结果,不同的是web service代码现在是由Groovy处理了。还有,就是你的应用中再也没有纯粹的Java代码了。哦,亲爱的。JavaFX创建了GUI,而Groovy则在后台干些脏累活(grunt work)。那么,该对纯粹的Java代码说声再见了?

编者注:首先应该说明一下,虽然JavaFX与Java之间可互操作,JavaFX在语法上也从Java中继承了很多,但是脚本语言JavaFX和Java并不是同一个概念。不过这篇文章自发布在JavaLobby上之后,得到了很多国外程序员的关注。当然,其中有人指出了作者犯的这个概念性错误:

“JavaFX不是Java!这批文章应该发表在Groovy区,它不应该出现在Java区,因为它跟Java毫不相关。”

不过,更多的讨论是围绕着Java平台语言未来的走向,以及做为程序员的选择而进行的。以下,51CTO编辑节选了部分精彩的讨论内容:

我喜欢groovy,但我们还是需要Java的。Groovy的性能以及内存消耗跟Java相比起来是可笑的。相比使用Groovy来取代Java(原文是replace better Java,即取代更好的Java),我更愿意选择Scala:它支持带静态类型的函数式编程,同时得益于类型推导,拥有许多优点。

——————

我认为性能不是问题,在动态语言方面VM(虚拟机)正变得越来越“聪明”。我有时使用groovy,“真的”很喜欢它,不过就是不习惯用动态类型。用它我省下的时间都被BUG吹飞了,除非编译器能捕获到它。这就是为什么我的第二选项是Scala,只要它有了更多的工具和供应商支持。

——————

对于大部分应用而言,Groovy表现已足够好(就像Ruby和PHP一样),Groovy代码不够快的时候,你可以写Java代码。此二者的集成是无缝的。同样,如果你不喜欢动态类型,那就使用静态类型吧。没人阻止你在Groovy里用静态类型。这正是它很棒的地方之一。如果你担心bug的困扰,因为自己使用了动态语言,我建议你进行单元测试,并使用一个好的持久的集成服务器。

——————

Groovy是“作为平台的Java”之上的一个更高级的语言,JavaFX甚至还要高些。Groovy、JavaFX和Java作为语言是“作为平台的Java”的不同的味道。在JavaLobby里面出现Groovy和JavaFX的新闻是有意义的。一旦某一天Groovy和JavaFX取得了压倒性的胜利,就有必要建立一个javafx区和Groovy区来避免每天出现过多的相关新闻,而java.dzone.com就将成为一个专门有关Java“语言”的社区。

之所以会这么说,是因为JavaFX是Sun(Oracle)提供的新基石,这是需要的,也不错。JavaFX可与Flash/Flex/AIR竞争,Groovy则有自己的位置,但是许多人(包括我在内)认为脚本语言管理复杂应用是有问题的,因为缺少编译器(是的我知道你可以编译Groovy)。给“非纯粹Java代码”唱颂歌可以理解,尽管这会促使就使用正确技术作出坏的决定。

脚本有用武之地,真的,在小规模应用(或者重复同样模式的应用)以及需要从外部读取源码的高度动态的应用。

我已经一遍又一遍地读过这样的例子:

def channel = new XmlParser().parse(url).channel 

“这简直就是酷毙了,尤其是再把它跟原来的丑陋代码比对过之后。”

我得说,那不是语言,而是API:原始的Java代码使用了SAX解析器,SAX解析器是个标记用的底层API,使用DOM的话会短一些(我确信Groovy在后台使用了DOM),Document.getDocumentElement()方法返回了channel节点。使用XPath及/或 TreeWalker能帮助以你在Groovy中以类似的方式跨越DOM。Java代码的确有点冗长,不过谁会在意呢?还有,如果你把某些典型的DOM代码打包进自建的客户化迷你API里面,你就会有跟Groovy一样的生产力。有一个问题,就是你得编译Java代码,但用Groovy和JavaFX就不用。是的,毫无疑问,如果编译阶段是个问题的话,Groovy和JavaFX就很美妙了。

【编辑推荐】

  1. JavaFX对Java开发者到底意味着什么
  2. JavaFX应用问题解答
  3. 基于JVM的语言正在开始流行
  4. 专题:Groovy开发技术
  5. 专题:Scala编程语言
责任编辑:yangsai 来源: 51CTO.com
相关推荐

2018-11-08 12:14:51

苹果库克iPhone

2019-11-27 09:07:42

Java模型项目

2009-06-23 14:44:29

调用JavaFX

2013-04-17 10:20:27

GroovyClassLoader

2022-09-30 00:00:00

云计算自动化IT

2018-10-18 12:42:24

2009-07-14 16:07:59

调用JavaFX代码Swing程序

2015-11-10 12:32:58

编程快乐程序员

2023-03-06 00:24:05

Kubernetes项目开源

2022-09-06 09:37:17

GroovyJava框架

2009-06-16 15:17:38

JavaFX

2012-11-30 13:29:15

2009-05-07 09:06:58

C++BuilderBorland

2018-03-05 08:59:21

Java 开源Oracle

2010-08-25 10:42:20

GroovyGroovy++

2009-09-03 11:47:43

Groovy与Java

2023-01-06 18:31:46

准确命名

2023-09-05 15:26:52

CTO程序员

2009-07-08 11:44:40

ScalaGroovyJVM

2021-04-28 09:15:21

技术社交距离网络
点赞
收藏

51CTO技术栈公众号