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.
All these packages and classes are imported by default, i.e. you do not have to use an explicit
to use them:
java.io.*
java.lang.*
java.math.BigDecimal
java.math.BigInteger
java.net.*
java.util.*
groovy.lang.*
groovy.util.*
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:
In Java, you would have:
Whereas in Groovy:
That is because Java will use the static information type, which is that
declared as an
will choose at runtime, when the method is actually called. Since it is called with a
then the
In Groovy, the
You actually have to use:
In Groovy, omitting a modifier on a field doesn’t result in a package-private field like in Java:
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
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:
can be written like this:
or, if you want a version closer to Java:
Here’s an example of static inner class:
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.
In Java you can do this:
Groovy doesn’t support the
Java 8 supports lambdas and method references:
Java 8 lambdas can be more or less considered as anonymous inner classes. Groovy doesn’t support that syntax, but has closures instead:
As double-quoted string literals are interpreted as
Groovy may fail with compile error or produce subtly different code if a class with
containing a dollar character is compiled with Groovy and Java compiler.
While typically, Groovy will auto-cast between
an API declares the type of a parameter, beware of Java APIs that accept an
and then check the actual type.
Singly-quoted literals in Groovy are used for
and double-quoted result in
depending whether there is interpolation in the literal.
Groovy will automatically cast a single-character
when assigning to a variable of type
When calling methods with arguments of type
need to either cast explicitly or make sure the value has been cast in advance.
Groovy supports two styles of casting and in the case of casting to
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.
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
In Java
equality of primitive types or identity for objects. In Groovy
to
and
identity, there is
Java does automatic widening and narrowing conversions.
Table 1. Java Conversions
* '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
* '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
Converting from a number to a character casts the
Groovy constructs
converting from a
otherwise it constructs using
Other conversions have their behavior defined by
There are a few more keywords in Groovy than in Java. Don’t use them for variable names etc.
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 importstatement
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
ois
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
Stringversion 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 GStringvalues,
Groovy may fail with compile error or produce subtly different code if a class with
Stringliteral
containing a dollar character is compiled with Groovy and Java compiler.
While typically, Groovy will auto-cast between
GStringand
Stringif
an API declares the type of a parameter, beware of Java APIs that accept an
Objectparameter
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
Stringor
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
Stringto
charonly
when assigning to a variable of type
char.
When calling methods with arguments of type
charwe
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
charthere
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 referencesto 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.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 | - |
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.
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 | - |
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
BigIntegerand
BigDecimalusing
Number.doubleValue()when
converting from a
Floator
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
相关文章推荐
- Java Wish List: The Top Differences Between Java, Scala, Groovy, Clojure and Kotlin
- Java-What is the difference between <? super E> and <? extends E>?
- The difference between java application library and java web lib
- The Differences Between C++ and Java
- The difference between scheduleAtFixedRate and scheduleWithFixedDelay in JAVA
- The difference of overriding between C# and Java
- What’s the difference between an interface and an abstract class in Java?
- the difference between final and static in java
- The differences between Java EE components and "standard" Java classes
- The Similarities and Differences Between C# and Java -- Part 1(译)
- What is the difference between a soft reference and a weak reference in Java?
- The difference between equals and == of Java
- The Similarities and Differences Between C# and Java -- Part 1(译)
- The difference between null and isEmpty in Groovy
- The differences between Java application and Java applet
- What's the difference between Future and FutureTask in Java?
- The difference between Const and ReadOnly
- Differences between C++ and Java
- The Differences Between Java, C And C++
- Similarities and Differences between Java and C++