1.groovy所有的包和classes是默认被导入
2.在groovy中,方法的调用是在运行时被选择。这被称为运行时调度和多方法。根据运行时参数类型选择方法。
在java中,这个是相反的,在编译时,根据定义的类型, 选择方法。
以下代码以Java代码的形式编写,可以在Java和Groovy中编译,但其行为会有所不同:
1 int method(String arg) {
2 return 1;
3 }
4 int method(Object arg) {
5 return 2;
6 }
7 Object o = "Object";
8 int result = method(o);
在java中 result的值是2,
在groovy中的值是1
java使用的是静态信息类型,o被声明为Object;然而groovy是在运行时选择,这个方法真正被调用的时候。因为o是一个String所以调运String的版本。
3.数组的初始化: 在Groovy中,{…}块保留给闭包。
java:
int[] array = { 1, 2, 3 }
groovy
int[] array = [ 1, 2, 3]
4.包范围的可见性
在groovy中,省略字段的修饰符,不会导致像在java中变成一个包私有字段。
相反,在groovy创建一个属性,即私有字段,关联getter,关联setter
通过注解@PackageScope来创建一个包私有字段
1 class Perso{
2 @PackageScope String name
3 }
5.ARM(Automatic Resource Management)模块( 自动资源管理)
Groovy不支持Java7中的ARM模块。
相反, Groovy提供了依赖于闭包的各种方法,闭包具有相同的效果,同时更具有惯用性
Path file = Paths.get("/path/to/file");
Charset charset = Charset.forName("UTF-8");
try (BufferedReader reader = Files.newBufferedReader(file, charset)) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
能被写成
new File('/path/to/file').eachLine('UTF-8') {
println it
}
如果你想要一个更接近Java的版本
new File('/path/to/file').withReader('UTF-8') { reader ->
reader.eachLine {
println it
}
}
6.内部类
匿名内部类和嵌套类的实现遵循Java的指导原则,但是您不应该去掉Java语言规范,而继续对不同的事情摇头叹息。实现看起来很像我们对groov.lang.Closure所做的。有一些好处也有一些不同。例如,访问私有字段和方法可能成为一个问题,但另一方面,局部变量不一定是最终的。
静态内部类:
class A {
static class B {}
}
new A.B()
静态内部类的使用最受支持。如果你绝对需要一个内部类,你应该设置它是一个静态内部类。
匿名内部类:
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
CountDownLatch called = new CountDownLatch(1)
Timer timer = new Timer()
timer.schedule(new TimerTask() {
void run() {
called.countDown()
}
}, 0)
assert called.await(10, TimeUnit.SECONDS)
创建一个非静态的内部类的实例
在Java中:
public class Y {
public class X {}
public X foo() {
return new X();
}
public static X createX(Y y) {
return y.new X();
}}
Groovy中不支持 y.new X() 。代替,你必须写成 new X(y), 就像下面的代码
public class Y {
public class X {}
public X foo() {
return new X()
}
public static X createX(Y y) {
return new X(y)
}
}
Groovy支持使用一个参数调用方法,而不提供参数参数,那么参数的值将为null。相同的规则应用在调用构造函数上。有一个危险,你写 new X() 代替 new X(this)。 因为这可能也是常规的方法,我们还没有找到一个好的方法来预防这个问题。
7.Lambdas
Java8支持lambdas和方法引用
Runnable run = () -> System.out.println("Run");
list.forEach(System.out::println);
Java8 lambdas 或多或少能看做事匿名内部类。
Groovy不支持这种语法,但是有闭包代替:
Runnable run = { println 'run' }
list.each { println it } // or list.each(this.&println)
8.GString
双引号的字符串的字面值被解释为GString类型的值。如果用Groovy和Java编译一个包含$符号的String,Groovy可能会编译报错或者产生微妙的不同代码
如果API 声明的参数的类,Groovy自动转换在GString和String之间。当心Java APIs,接受一个对象的参数并且检查实际类型。
9.String Character
在Groovy,单引号字面值被使用为String,双引号的结果是 String 或者 GString,取决于在字面值中是否有插入。
Groovy自动转换单个字符的字符串成为字符类型,仅仅是当分配的变量类型char。
当调用参数类型是char的方法时,我们需要显示的转换 或者确保这个值被提前转换。
Groovy支持2种风格的转换,当转换的是多个字符的字符串时,有一些不同。Groovy风格是更加宽容的,将转换第一个字符,然而C风格的转换将以exception失败
10.原始类型和包装类型
因为Groovy什么都是对象,它自动引用到原始类型。正因为这样,它不遵循java的行为,扩大 优先级到装箱
int i
m(i)
void m(long l) { // 1
println "in m(long)"
}
void m(Integer i) { //2
println "in m(Integer)"
}
1.java调用这个方法,认为 扩展 优先于 拆箱
2.Groovy调用这个方法,因为所有的原始类型引用到他们的的包装类。
11.==
在Java中 == 意味着 原始类型相同或 对象的一致性。
在Groovy 中 如果他们是可比较的并且a.equals(b), == 转换成a.compareTo(b)==0。为了核查一致性,可以使用is,例如 a.is(b)
12.转换(conversions)
13.额外的字段
Groovy中的关键词比Java中的多一些。不要将它们用于变量名等
as、def、in、trait