您的位置:首页 > Web前端

the differences between groovy and java

2017-05-12 17:03 471 查看
Groovy tries to be as natural as possible for Java developers. We’ve tried to follow the principle of least surprise when designing Groovy, particularly for developers learning Groovy who’ve come from a Java background.

Here we list all the major differences between Java and Groovy.


1. Default imports

All these packages and classes are imported by default, i.e. you do not have to use an explicit 
import
 statement
to use them:

java.io.*

java.lang.*

java.math.BigDecimal

java.math.BigInteger

java.net.*

java.util.*

groovy.lang.*

groovy.util.*


2. Multi-methods

In Groovy, the methods which will be invoked are chosen at runtime. This is called runtime dispatch or multi-methods. It means that the method will be chosen based on the types of the arguments at runtime. In Java,
this is the opposite: methods are chosen at compile time, based on the declared types.

The following code, written as Java code, can be compiled in both Java and Groovy, but it will behave differently:

int method(String arg) {
return 1;
}
int method(Object arg) {
return 2;
}
Object o = "Object";
int result = method(o);


In Java, you would have:

assertEquals(2, result);


Whereas in Groovy:

assertEquals(1, result);


That is because Java will use the static information type, which is that 
o
 is
declared as an 
Object
, whereas Groovy
will choose at runtime, when the method is actually called. Since it is called with a 
String
,
then the 
String
 version is called.


3. Array initializers

In Groovy, the 
{
…​ }
 block is reserved for closures. That means that you cannot create array literals with this syntax:

int[] array = { 1, 2, 3}


You actually have to use:

int[] array = [1,2,3]



4. Package scope visibility

In Groovy, omitting a modifier on a field doesn’t result in a package-private field like in Java:

class Person {
String name
}


Instead, it is used to create a property, that is to say a private field, an associated getter and an associated setter.

It is possible to create a package-private field by annotating it with 
@PackageScope
:

class Person {
@PackageScope String name
}



5. ARM blocks

ARM (Automatic Resource Management) block from Java 7 are not supported in Groovy. Instead, Groovy provides various methods relying on closures, which have the same effect while being more idiomatic. For example:

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();
}


can be written like this:

new File('/path/to/file').eachLine('UTF-8') {
println it
}


or, if you want a version closer to Java:

new File('/path/to/file').withReader('UTF-8') { reader ->
reader.eachLine {
println it
}
}



6. Inner classes

The implementation of anonymous inner classes and nested classes follows the Java lead, but you should not take out the Java Language Spec and keep shaking the head about things that are different. The implementation
done looks much like what we do for 
groovy.lang.Closure
,
with some benefits and some differences. Accessing private fields and methods for example can become a problem, but on the other hand local variables don’t have to be final.


6.1. Static inner classes

Here’s an example of static inner class:

class A {
static class B {}
}

new A.B()


The usage of static inner classes is the best supported one. If you absolutely need an inner class, you should make it a static one.


6.2. Anonymous Inner Classes

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)



6.3. Creating Instances of Non-Static Inner Classes

In Java you can do this:

public class Y {
public class X {}
public X foo() {
return new X();
}
public static X createX(Y y) {
return y.new X();
}
}


Groovy doesn’t support the 
y.new
X()
 syntax. Instead, you have to write 
new
X(y)
, like in the code below:

public class Y {
public class X {}
public X foo() {
return new X()
}
public static X createX(Y y) {
return new X(y)
}
}


Caution though, Groovy supports calling methods with one parameter without giving an argument. The parameter will then have the value null. Basically the same rules apply to calling a constructor. There is a danger that
you will write new X() instead of new X(this) for example. Since this might also be the regular way we have not yet found a good way to prevent this problem.


7. Lambdas

Java 8 supports lambdas and method references:

Runnable run = () -> System.out.println("Run");
list.forEach(System.out::println);


Java 8 lambdas can be more or less considered as anonymous inner classes. Groovy doesn’t support that syntax, but has closures instead:

Runnable run = { println 'run' }
list.each { println it } // or list.each(this.&println)



8. GStrings

As double-quoted string literals are interpreted as 
GString
 values,
Groovy may fail with compile error or produce subtly different code if a class with 
String
 literal
containing a dollar character is compiled with Groovy and Java compiler.

While typically, Groovy will auto-cast between 
GString
 and 
String
 if
an API declares the type of a parameter, beware of Java APIs that accept an 
Object
 parameter
and then check the actual type.


9. String and Character literals

Singly-quoted literals in Groovy are used for 
String
,
and double-quoted result in 
String
 or 
GString
,
depending whether there is interpolation in the literal.

assert 'c'.getClass()==String
assert "c".getClass()==String
assert "c${1}".getClass() in GString


Groovy will automatically cast a single-character 
String
 to 
char
 only
when assigning to a variable of type 
char
.
When calling methods with arguments of type 
char
 we
need to either cast explicitly or make sure the value has been cast in advance.

char a='a'
assert Character.digit(a, 16)==10 : 'But Groovy does boxing'
assert Character.digit((char) 'a', 16)==10

try {
assert Character.digit('a', 16)==10
assert false: 'Need explicit cast'
} catch(MissingMethodException e) {
}


Groovy supports two styles of casting and in the case of casting to 
char
 there
are subtle differences when casting a multi-char strings. The Groovy style cast is more lenient and will take the first character, while the C-style cast will fail with exception.

// for single char strings, both are the same
assert ((char) "c").class==Character
assert ("c" as char).class==Character

// for multi char strings they are not
try {
((char) 'cx') == 'c'
assert false: 'will fail - not castable'
} catch(GroovyCastException e) {
}
assert ('cx' as char) == 'c'
assert 'cx'.asType(char) == 'c'



10. Primitives and wrappers

Because Groovy uses Objects for everything, it autowraps references
to primitives. Because of this, it does not follow Java’s behavior of widening taking priority over boxing. Here’s an example using 
int


int i
m(i)

void m(long l) {
println "in m(long)"
}

void m(Integer i) {
println "in m(Integer)"
}


This is the method that Java would call, since widening has precedence over unboxing.
This is the method Groovy actually calls, since all primitive references use their wrapper class.


11. Behaviour of 
==

In Java 
==
 means
equality of primitive types or identity for objects. In Groovy 
==
 translates
to 
a.compareTo(b)==0
, if they are 
Comparable
,
and 
a.equals(b)
 otherwise. To check for
identity, there is 
is
. E.g. 
a.is(b)
.


12. Conversions

Java does automatic widening and narrowing conversions.

Table 1. Java Conversions
 Converts to

Converts from
boolean

byte

short

char

int

long

float

double

boolean
-

N

N

N

N

N

N

N

byte
N

-

Y

C

Y

Y

Y

Y

short
N

C

-

C

Y

Y

Y

Y

char
N

C

C

-

Y

Y

Y

Y

int
N

C

C

C

-

Y

T

Y

long
N

C

C

C

C

-

T

T

float
N

C

C

C

C

C

-

Y

double
N

C

C

C

C

C

C

-

* 'Y' indicates a conversion Java can make, 'C' indicates a conversion Java can make when there is an explicit
cast, 'T` indicates a conversion Java can make but data is truncated, 'N' indicates a conversion Java can’t make.

Groovy expands greatly on this.

Table 2. Groovy Conversions
 Converts to

Converts from
boolean

Boolean

byte

Byte

short

Short

char

Character

int

Integer

long

Long

BigInteger

float

Float

double

Double

BigDecimal

boolean
-

B

N

N

N

N

N

N

N

N

N

N

N

N

N

N

N

N

Boolean
B

-

N

N

N

N

N

N

N

N

N

N

N

N

N

N

N

N

byte
T

T

-

B

Y

Y

Y

D

Y

Y

Y

Y

Y

Y

Y

Y

Y

Y

Byte
T

T

B

-

Y

Y

Y

D

Y

Y

Y

Y

Y

Y

Y

Y

Y

Y

short
T

T

D

D

-

B

Y

D

Y

Y

Y

Y

Y

Y

Y

Y

Y

Y

Short
T

T

D

T

B

-

Y

D

Y

Y

Y

Y

Y

Y

Y

Y

Y

Y

char
T

T

Y

D

Y

D

-

D

Y

D

Y

D

D

Y

D

Y

D

D

Character
T

T

D

D

D

D

D

-

D

D

D

D

D

D

D

D

D

D

int
T

T

D

D

D

D

Y

D

-

B

Y

Y

Y

Y

Y

Y

Y

Y

Integer
T

T

D

D

D

D

Y

D

B

-

Y

Y

Y

Y

Y

Y

Y

Y

long
T

T

D

D

D

D

Y

D

D

D

-

B

Y

T

T

T

T

Y

Long
T

T

D

D

D

T

Y

D

D

T

B

-

Y

T

T

T

T

Y

BigInteger
T

T

D

D

D

D

D

D

D

D

D

D

-

D

D

D

D

T

float
T

T

D

D

D

D

T

D

D

D

D

D

D

-

B

Y

Y

Y

Float
T

T

D

T

D

T

T

D

D

T

D

T

D

B

-

Y

Y

Y

double
T

T

D

D

D

D

T

D

D

D

D

D

D

D

D

-

B

Y

Double
T

T

D

T

D

T

T

D

D

T

D

T

D

D

T

B

-

Y

BigDecimal
T

T

D

D

D

D

D

D

D

D

D

D

D

T

D

T

D

-

* 'Y' indicates a conversion Groovy can make, 'D' indicates a conversion Groovy can make when compiled dynamically
or explicitly cast, 'T` indicates a conversion Groovy can make but data is truncated, 'B' indicates a boxing/unboxing operation, 'N' indicates a conversion Groovy can’t make.

The truncation uses Groovy Truth when converting
to 
boolean
/
Boolean
.
Converting from a number to a character casts the 
Number.intvalue()
 to 
char
.
Groovy constructs 
BigInteger
 and 
BigDecimal
 using 
Number.doubleValue()
 when
converting from a 
Float
 or 
Double
,
otherwise it constructs using 
toString()
.
Other conversions have their behavior defined by 
java.lang.Number
.


13. Extra keywords

There are a few more keywords in Groovy than in Java. Don’t use them for variable names etc.

as


def


in


trait
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: