groovy脚本
正如我的博客标题所暗示的那样,我的许多博客文章都是受实际事件启发的 。 本周的三种经历再次使我想起了Groovy编写脚本的简单性。 在本文中,我简要地介绍了这三个事件中的每一个,它们仅是相关的,因为它们与Groovy以及与Groovy的脚本相关联。
Groovy为Java开发人员提供简单的脚本编写
在“ 我使用main()方法”一文中 , Bozhidar Bozhanov写道,他“ [使用]具有主要方法的工具类”,而不是在Linux / bash或Windows PowerShell中编写脚本。 Bozhanov去解释了这个决定:
Java有很多功能强大的库,这些库使我可以摆脱在Shell中执行操作或使用bash脚本的需要。 好处是–它是Java,可以根据需要对其进行版本控制,并且易于使用,无需额外的学习过程,无需手册页等。
尽管我被困于编写和维护Perl,并且已知使用其他脚本语言,例如Ruby , Python , PHP和Shell / bash或PowerShell ,但我也感谢Bozhanov偏爱带有main()函数的Java类的原因。用于开发工具。 JDK和JVM提供了功能强大且功能丰富的库和功能,作为Java开发人员,我对此很熟悉。
对于那些对JDK和JVM比对底层操作系统更熟悉的人来说,Groovy是一种很棒的脚本语言。 对于Java开发人员来说,Groovy很容易掌握,并且使某些事情比用Java编写时更容易。 Groovy在提供“脚本样式”特性方面特别出色,例如无需编写显式对象,无需编写public static void main
方法定义,无需捕获异常(选中或未选中),内置命令行支持 , JDK的许多有用的GDK 扩展 ,动态键入, 简洁的语法 ( 单行是极端示例 ),易于访问的根类加载器以进行内部类加载, 报告友好的输出功能 , 集成的Ant支持 , 便捷SQL访问 , 便捷的XML解析 , 改进的正则表达式支持等。
与其他一些脚本语言相比,使用Groovy进行脚本编写的一个优势是能够在支持Java虚拟机的任何平台上运行Groovy脚本。
Groovy增加了Java知识
我还用简单的Java主类在博客上学习了该语言 。 本周早些时候,一位同事遇到了与Double.MIN_VALUE有关的令人惊讶的发现。 当他问我是否知道Double.MIN_VALUE的值是什么时,我告诉他我不知道该怎么做,但随后几秒钟就可以通过在上面运行以下简单命令来告诉他命令行:
groovy -e "println Double.MIN_VALUE"
如下面的屏幕快照所示,运行此单行命令的输出为4.9E-324。 他问我,因为他(现在让我感到惊讶)这不是负面的。 在为Double.MIN_VALUE读取Javadoc之后,这个值就很有意义了,但是对我来说,通过运行该简单的Groovy脚本来查找该值比访问Javadoc甚至Google更快。 我反复发现Groovy对于快速学习Java有很大的帮助。
顺便说一下, Javadoc for Double.MIN_VALUE声明了状态(我加了强调 ),“一个常量,它持有double类型的最小正非零值 2-1074。 它等于十六进制浮点文字0x0.0000000000001P-1022,也等于Double.longBitsToDouble(0x1L)。” 我以为它是一个负数,因为我以前从未使用过它,并且因为我以前使用Integer.MIN_VALUE和Long.MIN_VALUE为负值的经验。 在Java上的StackOverflow线程最小值和Double.MIN_VALUE中可以找到有关选择Double.MIN_VALUE
(并适用于Float.MIN_VALUE)的原因的详细讨论。
Groovy简化了本机集成
尽管使用Groovy编写脚本的优点之一是能够在支持JVM的任何平台上运行Groovy脚本,但是在许多情况下,脚本需要访问本机操作系统。 Groovy可以通过Java的java.lang.Runtime和java.lang.Process访问本机操作系统。 Groovy通过其Process类的JDK扩展简化了这些类的使用。
JDK Process类具有一个waitFor()方法,该方法的Javadoc描述状态(我强调了 ):
如有必要,使当前线程等待,直到此Process对象表示的进程终止。 如果子进程已经终止,则此方法立即返回。 如果子进程尚未终止,则调用线程将被阻塞,直到子进程退出 。
用于Process的类级Javadoc更清楚地概述了潜在的负面影响(我特别强调 ):
由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小 ,因此未能及时写入子流程的输入流或读取子流程的输出流可能会导致子流程阻塞甚至死锁 。
2000年的JavaWorld优秀文章Runtime.exec()不会显示使用Java代码编写输入和读取输出以避免块或死锁的示例,但是Groovy的Process GDK增强功能使此操作更加容易。 例如,Groovy GDK Process.waitForProcessOutput(Appendable,Appendable)方法允许两个StringBuilder实例(例如,代表标准输出和标准错误缓冲区)来防止“由于输出缓冲区已满而导致进程阻塞”。
接下来的两个代码清单以及与脚本输出关联的屏幕快照对此进行了演示。
demoDeadlock.groovy – Process.waitFor()死锁
#!/usr/bin/env groovy
def recursiveDirCmd = "cmd /c dir /s ${args[0]}"
println "Running command ${recursiveDirCmd}..."
def result = recursiveDirCmd.execute()
result.waitFor()
println result.in.text
demoNoDeadlock.groovy – Process.waitForProcessOutput(Appendable,Appendable)不死锁
#!/usr/bin/env groovy
def recursiveDirCmd = "cmd /c dir /s ${args[0]}"
println "Running command ${recursiveDirCmd}..."
StringBuilder standard = new StringBuilder(450000)
StringBuilder error = new StringBuilder(450000)
def result = recursiveDirCmd.execute()
result.waitForProcessOutput(standard, error)
println standard
上面的代码清单和相关的屏幕快照展示了Groovy对Process
的GDK扩展,可以轻松地避免阻塞针对底层操作系统执行的命令。 关于从Groovy代码调用Shell命令的好文章是在Groovy中执行Shell命令 。
结论
本周发生了三起不同的事件,这增强了我对Groovy的看法,该观点将Java的强大功能与Groovy的脚本编写简单性相结合。
翻译自: https://www.javacodegeeks.com/2013/12/sublime-simplicity-of-scripting-with-groovy.html
groovy脚本