感觉里面涉及到的技术比较老了, 现在说到java脚本语言, 谁会提到beanshell之流, 我只看了里面关于groovy相关的内容, 感觉里面介绍的groovy都比较过时了, 比如不支持for循环, 我不知道groovy哪个版本不支持和的, 反正我使用的几个版本(1.6+)没有这样的问题. 翻译的一般, 而且有一些很细微的错误, 审核的该打pp^_^
一个好的程序员理当可以维护大约2w行代码, 无论这是两万行汇编, c或者高级语言代码, 它还是2w行, 如果你的语言要求用更好的代码行来表达相同的思想, 你就可以在那2w行之外的事情上多花点时间
2w行Python程序可能是10w行java或c++程序
程序员没有理由只习惯于一种编程语言
试图给每一项编程任务使用一种语言就像试图给每一项木工活使用一种工具一样.
什么工作选择最适合用什么工具
unix程序员关注创建简单的过滤器程序, 而不是创建复杂的单一应用程序.
快速开发和易于重构是脚本的重点
再简单的系统管理任务, 如果超过两次就都没有乐趣可言了.
如果你发现自己在重复地做一些简单的手动任务, 就应该努力使这些任务自动化
这些任务执行的多快并不重要, 因为他们都是周期的执行, 而且大多数都是在系统闲置的时候执行.
脚本语言有更高的抽象级别, 换句话说更加面向人类, 因此学习脚本语言的基本概念相对比较容易.
java api 以及jvm形成了java运行时环境 jre
java脚本语言两种运行模式:
1.给在jvm内部运行的特定编程语言实现一种解释器, 用来将这种脚本语法解析成java字节码.
2.创建一个专门的类加载器来加载被解析的脚本, 这种脚本被加载为jvm中普通的java类
Groovy使用java语法, 但是除此之外, 他还提供了一些从Python, Ruby和SmallTalk引进的概念.
支持弱类型, 变量不需要使用之前定义, 允许不进行任何类型定义.
Groovy直接编译成java字节码
与Jython不同, 没有生成任何中间的.java文件.
Groovy通过抛弃getter和setter方法而简化JavaBean. 另外强化了循环, 转换语句, 自动装箱和操作符重载的得到增强.
Groovy最重要的特征是它类似于java语法.
开发人员必须扎实掌握两种语言, 一种系统语言, 一种脚本语言.
Python对于java人员来说可能有点难于理解. 每天同时使用, 需要在两种不同的语法之间进行大量的思维转换, 会降低开发速度.
可以用def来定义方法
方法和变量没必要在使用之前定义.
如果定义了和脚本同名的类, 就不能在类的外部编写弱类型语句
比如创建一个A.groovy文件
里面定义了
class B{
...
}
class C {
...
}
//接着写下面的语句是可以的, 如果定义了class A{...} 则下面的语句不允许
println ...
def method(){
...
}
动态性是脚本语言最重要的特征之一.
动态的类型并不强制你给变量和属性, 或者方法参数和返回值定义类型. 类型在赋值的时候会自动确定, 它们以后在分配(返回)新值的时候还可以修改, 而弱类型表示在一个操作发生之前, 变量还可以被转换成最适合的类型.
Groovy中不需要定义一个公共的接口.
可以这样写:
def method(item){...}
Groovy把一切都看成对象, 这样避免了基本类型和包装类型之间的转换.
整数字符转换为它们最适合的最小类型, 比如Integer. 包含十进制小数点的文字被转换为BigDecimal类.
字符串是脚本语言中最重要的数据类型之一. Groovy中有一个三重引用(Triple-Quote)"""..."""
Groovy提供了GString类型, 这样可以允许你能够将表达式嵌入到一个字符串中, 这样使得GString对象天生就能够执行模板处理和变量置换. 嵌入表达式语法是${expression}
GSTring类使用"延迟表达式执行求值", 即表达式直到需要对象的字符串值时才会被执行求值.
正则表达式
java这样写:
Pattern p = Pattern.compile("(ab)*")
Matcher m = p.matcher("ababababab")
if (m.matches()){
...
}
Groovy这样写:
p = ~"(ab)*"
m = "ababababab" =~ p
if (m.matches()) {
println "data is valid"
}else {
println "data is invalid"
}
~"pattern" 创建Pattern对象, 相当于Pattern.compile("pattern")
"text" =~ pattern 创建Matcher对象, 相当于pattern.matcher("text")
这个没用过, 记录一下
m = "abab" =~ "(ab)*"
println m.replaceAll("cd")
Groovy引入了==~操作符, 相当于:
Pattern.compile("pattern").matcher("text").matches()
比如这样写:
if ("abababa" ==~ "(ab)*"){
...
}
集合处理是基本的编程任务之一
List创建在Groovy中类似于java中创建数组
Groovy增加了<<操作符来简化添加元素的操作.
一些常用的集合操作的方法
count: 返回指定元素出现的次数
min/max返回list中最小/最大值, 需要接受Comparator/Closure对象
intersect: 返回并集
join:返回给定的字符串连接List元素的字符串.
Groovy另一种常用的新特性Range.
..表达式用来创建包括末尾边界的范围, ..<表达式则不包括边界值.
Range被实现为一个ArrayList, 可以用任何类型的对象定义范围, 但是他们只在这些对象实现Comparable接口时才有意义.
getFrom() :得到范围的起始边界
getTo(): 得到范围的结束边界
contains(): 检查指定的元素是否在范围中.
利用Range语法创建包含两个中间元素的一个sublist:
list = ["groovy", "python", "beanshell", "ruby"]
sublist = list[1..2] // ["python", "beanshell"]
任何对象都可以用作键, 但是为了符合JavaBean语法, 键应该为字符串, 如果我们试图在包含非字符串的键中使用JavaBean语法会抛出异常.
map=[1:"first", 2:"second"]
map[1] // first
map.get(1) // first
map.1 // 抛异常
Groovy可以将一个switch变量与下列条件进行比较:
类名
正则
集合中的成员
精确的值
对于switch语法, Groovy做了扩展, 对于switch结构:
switch(switchValue){
caseValue: // action
}
Groovy用switchValue作为参数, 在caseValue对象中调用isCase(Object obj)方法, 默认情况下, 许多类都重载了isCase语法, 比如这样写:
class Dog{
public isCase(switchValue) {
if (["a", "b"].contains(switchValue)) {
return true;
}else {
return false
}
}
}
def test(aa) {
dog = new Dog();
switch(aa) {
case dog: println "it's dog";break;
default : println "not dog";break;
}
}
test("a") // it's dog
test("b");// it's dog
test("c");//not dog
Groovy中的for循环支持这样的格式:
for(i in 0..9){...}
在Groovy中定义的所有对象都实现了GroovyObject接口, 这样可以帮助我们处理未实现的方法, 该类提供了方法:
Object invokeMethod(String name, Object args);
每次调用某些方法的时候, 这个方法都会被调用, 你可以覆盖这个方法来扩展你类的功能, 并拦截对它方法的调用.
class MyClass{
def callMe(arg) {
return arg.toUpperCase();
}
public invokeMethod(String name, Object arg) {
if (name == "me") {
name = "callMe";
}
try {
return metaClass.invokeMethod(this, name, arg);
}catch(MissingMethodException e) {
return "method $name:$arg is not defined for this class;"
}
}
}
o = new MyClass();
println o.callMe("some string");
println o.callMe("one", "second")
println o.me("three")
操作符重载, 写个例子:
class Item{
}
class Basket{
def plus(Item item) {
println "basket and item"
}
}
i = new Item();
b = new Basket();
b+i
在GroovyBean中, 属性和方法的默认是public, 不是protected
GroovyBean可以通过在构造器调用中传递以冒号隔开的键值对进行构建:
car = new Car(model:"BMW")
对象导航
car.name相当于car.getName
为了避免导航GroovyBean时NullPointerException, 可以使用Groovy的安全导航语法
为了使导航安全地通过Bean, 就是用?.操作符, 而不是.操作符
car?.man?.country
闭包, 是Groovy中最重要的语法之一.
闭包基本上是扩展groovy.lang.Closure类的类, 闭包的语法集中在call()方法中, 因为他们是类, 可以直接传递给其他方法.
Groovy中的List和Map都有接受闭包参数的额外方法, 他们的目标是提供更方便的迭代集合的方法
each
用来直接迭代集合中的每一个元素
collect
利用指定的闭包转换集合中的元素. //我觉得取名translate更合适
[1,2,3,4].collect{it*2} // [2,4,6,8]
而这里不能用each来做同样的事情, 因为each不会改变原有的集合.collect返回一个修改过的新的集合.
inject
将前一次迭代的结果传递给下一个 // 很难理解的一个方法
println ([2,3,4,5].inject( 1) {pre, element->pre*element; }) // 120 , 相当于连乘
every
检查集中的每一个元素是否符合条件, 该方法返回一个boolean值
any
返回一个boolean值, 表示是否有任何项目符合条件
find
找出集合中某个条件的第一次出现的项目
findAll
找出几何中如何条件的所有项目
getText
读取文件内容, 不需要Reader对象实例, 关闭语句和异常处理, 我们所要做的就是编写脚本的业务逻辑, Groovy会处理剩下的工作.
text = new File("foo.txt").getText()
eachLine
读取文件的每一行
eacheLines
返回所有行的集合
lineList = new File("foo.txt").eachLines()
lineList.each{...}
splitEachLine
Groovy往往使一般的任务尽可能的简单, 用来对每一行的内容进行切分, 比较适合处理csv这样的规则文件.
new File("Foo.csv").splitEachLine(","){
it.each{
println "name=${it[0]}, age=${it[1]}"
}
}
eachByte(s)
用来处理二进制文件, 比较合适
write(append)
如何将文本写到文件
eachFile
枚举文件夹下的所有文件
Groovy提供了GroovyShell用来直接执行脚本
GroovyShell shell = new GroovyShell()
Object result = shell.evalute("x=1; y=2; return x+y")
println result ; // 3
可以将参数通过Binding传给给要执行的脚本
Binding binding = new Binding();
binding.setVariable("name", "Groovy")
shell.evalute(new File("foo.groovy"))
foo.groovy:
name:${name}
使用groovy脚本中定义的方法和类
public class Test {
public static void main(String[] args) {
GroovyClassLoader loader = new GroovyClassLoader();
GroovyObject go = null;
try {
Class clazz = loader.parseClass(new File("MyTest.groovy"));
go = (GroovyObject) clazz.newInstance();
} catch (CompilationFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
go.invokeMethod("test", new Object[] {});
}
}
def test() {
println "haha"
}