Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011
1. Groovy Update
What’s new in Groovy 1.8
and what’s coming next!
Guillaume Laforge
Groovy Project Manager
SpringSource / VMware
mercredi 18 mai 2011
2. Guillaume Laforge
• Groovy Project Manager
• JSR-241 Spec Lead
• Head of Groovy Development
at SpringSource / VMWare
• Initiator of the Grails framework
• Creator of the Gaelyk toolkit
• Co-author of Groovy in Action
• Speaker: JavaOne, QCon, JavaZone, Sun TechDays,
Devoxx, The Spring Experience, SpringOne, JAX,
Dynamic Language World, IJTC, and more...
2
mercredi 18 mai 2011
3. Guillaume Laforge
• Groovy Project Manager
• JSR-241 Spec Lead
• Head of Groovy Development
at SpringSource / VMWare
• Initiator of the Grails framework
• Creator of the Gaelyk toolkit
• Co-author of Groovy in Action
• Speaker: JavaOne, QCon, JavaZone, Sun TechDays,
Devoxx, The Spring Experience, SpringOne, JAX,
Dynamic Language World, IJTC, and more...
2
mercredi 18 mai 2011
16. Command chains expressions
• A grammar improvement allowing you to
drop dots & parens when chaining method calls
– an extended version of top-level statements like println
6
mercredi 18 mai 2011
17. Command chains expressions
• A grammar improvement allowing you to
drop dots & parens when chaining method calls
– an extended version of top-level statements like println
6
mercredi 18 mai 2011
18. Command chains expressions
• A grammar improvement allowing you to
drop dots & parens when chaining method calls
– an extended version of top-level statements like println
• Less dots, less parens allow you to
– write more readable business rules
– in almost plain English sentences
•(or any language, of course)
6
mercredi 18 mai 2011
19. Command chains expressions
• A grammar improvement allowing you to
drop dots & parens when chaining method calls
– an extended version of top-level statements like println
• Less dots, less parens allow you to
– write more readable business rules
– in almost plain English sentences
•(or any language, of course)
6
mercredi 18 mai 2011
20. Command chains expressions
• A grammar improvement allowing you to
drop dots & parens when chaining method calls
– an extended version of top-level statements like println
• Less dots, less parens allow you to
– write more readable business rules
– in almost plain English sentences
•(or any language, of course)
• Let’s have a look at some examples
6
mercredi 18 mai 2011
26. LookM a!
N op are ns,
no do ts!
mercredi 18 mai 2011
27. Command chains expressions
Before... we used to do...
take 2.pills, of: chloroquinine, after: 6.hours
9
mercredi 18 mai 2011
28. Command chains expressions
Before... we used to do...
take 2.pills, of: chloroquinine, after: 6.hours
Normal argument
9
mercredi 18 mai 2011
29. Command chains expressions
Before... we used to do...
take 2.pills, of: chloroquinine, after: 6.hours
Normal argument Named arguments
9
mercredi 18 mai 2011
30. Command chains expressions
Before... we used to do...
take 2.pills, of: chloroquinine, after: 6.hours
Normal argument Named arguments
Woud call:
def take(Map m, Quantity q)
9
mercredi 18 mai 2011
31. Command chains expressions
Now, even less punctuation!
take 2.pills of chloroquinine after 6.hours
10
mercredi 18 mai 2011
32. Command chains expressions
Now, even less punctuation!
( ). ( ). ( )
take 2.pills of chloroquinine after 6.hours
10
mercredi 18 mai 2011
33. Command chains expressions
// environment initialization
Integer.metaClass.getPills { ‐> delegate }
Integer.metaClass.getHours { ‐> delegate }
// variable injection
def chloroquinine = /*...*/
{ }
// implementing the DSL logic
def take(n) {
[of: { drug ‐>
[after: { time ‐> /*...*/ }]
}]
}
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
take 2.pills of chloroquinine after 6.hours
11
mercredi 18 mai 2011
35. Command chains expressions
take 2.pills of chloroquinine after 6.hours
... some dots remain ...
12
mercredi 18 mai 2011
36. Command chains expressions
We could cheat a bit...
take 2 pills of chloroquinine 6 hours after
13
mercredi 18 mai 2011
37. Command chains expressions
We could cheat a bit...
( ). ( ). ( ). ( )
take 2 pills of chloroquinine 6 hours after
13
mercredi 18 mai 2011
38. Cheating
is playing
with the
language
mercredi 18 mai 2011
39. Command chains expressions
Still doable without cheating though
take 2 pills of chloroquinine after 6 hours
15
mercredi 18 mai 2011
40. Command chains expressions
Still doable without cheating though
( ). ( ). ( ). ( )
take 2 pills of chloroquinine after 6 hours
15
mercredi 18 mai 2011
41. Command chains expressions
// variable injection
def (of, after, hours) = /*...*/
// implementing the DSL logic
{ }
def take(n) {
[pills: { of ‐>
[chloroquinine: { after ‐>
['6': { time ‐> }]
}]
}]
}
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
take 2 pills of chloroquinine after 6 hours
16
mercredi 18 mai 2011
43. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
17
mercredi 18 mai 2011
44. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
// leverage named‐args as punctuation
check that: margarita tastes good
17
mercredi 18 mai 2011
45. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
// leverage named‐args as punctuation
check that: margarita tastes good
// closure parameters for new control structures
given {} when {} then {}
17
mercredi 18 mai 2011
46. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
// leverage named‐args as punctuation
check that: margarita tastes good
// closure parameters for new control structures
given {} when {} then {}
// zero‐arg methods require parens
select all unique() from names
17
mercredi 18 mai 2011
47. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
// leverage named‐args as punctuation
check that: margarita tastes good
// closure parameters for new control structures
given {} when {} then {}
// zero‐arg methods require parens
select all unique() from names
// possible with an odd number of terms
take 3 cookies
17
mercredi 18 mai 2011
48. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
( ). ( ). ( )
// leverage named‐args as punctuation
check that: margarita tastes good
// closure parameters for new control structures
given {} when {} then {}
// zero‐arg methods require parens
select all unique() from names
// possible with an odd number of terms
take 3 cookies
17
mercredi 18 mai 2011
49. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
( ). ( ). ( )
// leverage named‐args as punctuation
check that: margarita tastes good
( ). ( )
// closure parameters for new control structures
given {} when {} then {}
// zero‐arg methods require parens
select all unique() from names
// possible with an odd number of terms
take 3 cookies
17
mercredi 18 mai 2011
50. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
( ). ( ). ( )
// leverage named‐args as punctuation
check that: margarita tastes good
( ). ( )
// closure parameters for new control structures
given {} when {} then {}
( ). ( ). ( )
// zero‐arg methods require parens
select all unique() from names
// possible with an odd number of terms
take 3 cookies
17
mercredi 18 mai 2011
51. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
( ). ( ). ( )
// leverage named‐args as punctuation
check that: margarita tastes good
( ). ( )
// closure parameters for new control structures
given {} when {} then {}
( ). ( ). ( )
// zero‐arg methods require parens
select all unique() from names
( ). . ( )
// possible with an odd number of terms
take 3 cookies
17
mercredi 18 mai 2011
52. Command chains expressions
// methods with multiple arguments (commas)
take coffee with sugar, milk and liquor
( ). ( ). ( )
// leverage named‐args as punctuation
check that: margarita tastes good
( ). ( )
// closure parameters for new control structures
given {} when {} then {}
( ). ( ). ( )
// zero‐arg methods require parens
select all unique() from names
( ). . ( )
// possible with an odd number of terms
take 3 cookies
( ).
17
mercredi 18 mai 2011
53. Runtime perf. improvements
• Significant runtime improvements
for primitive int operations
– classical Fibonacci example x13 faster!
– almost as fast as Java
• Some direct method calls on this
• But there’s more to come!
– in particular for all the primitive types
• But Jochen «blackdrag»
will tell you more on that!
18
mercredi 18 mai 2011
54. GPars bundled
• GPars is bundled in the Groovy distribution
• GPars covers a wide range of parallel and
concurrent paradigms
– actors, fork/join, dataflow, agents, STM...
• Václav Pech will cover the details on GPars
19
mercredi 18 mai 2011
55. Closure enhancements
• Closure annotation parameters
• Some more functional flavor
– composition
– trampoline
– memoization
• Currying improvements
20
mercredi 18 mai 2011
56. Closure annotation parameters
@Retention(RetentionPolicy.RUNTIME)
@interface Invariant {
Class value() // a closure class
}
{ @Invariant({ number >= 0 })
class Distance {
float number
String unit
}
def d = new Distance(number: 10, unit: "meters")
def anno = Distance.getAnnotation(Invariant)
def check = anno.value().newInstance(d, d)
assert check(d)
21
mercredi 18 mai 2011
57. Closure annotation parameters
@Retention(RetentionPolicy.RUNTIME)
@interface Invariant {
Class value() // a closure class
}
{ @Invariant({ number >= 0 })
class Distance {
float number P oor-m
miss
Cont
Andr
racts
an’s G é’s talk!
String unit Don’t
}
def d = new Distance(number: 10, unit: "meters")
def anno = Distance.getAnnotation(Invariant)
def check = anno.value().newInstance(d, d)
assert check(d)
21
mercredi 18 mai 2011
79. New AST transformations
• @Log • @Canonical
– @ToString,
• @Field – @EqualsAndHashCode,
– @TupleConstructor
• @AutoClone
• @InheritConstructor
• @AutoExternalizable
• @WithReadLock
• Controlling the execution
of your code • @WithWriteLock
– @ThreadInterrupt,
– @TimedInterrupt, • @ListenerList
– @ConditionalInterrupt
30
mercredi 18 mai 2011
80. @Log
• Four different loggers can be injected
– @Log, @Commons, @Log4j, @Slf4j
• Possible to implement your own strategy
import groovy.util.logging.*
@Log
class Car {
Car() {
log.info 'Car constructed'
}
}
def c = new Car()
31
mercredi 18 mai 2011
81. @Log
• Four different loggers can be injected
– @Log, @Commons, @Log4j, @Slf4j
• Possible to implement your own strategy
import groovy.util.logging.*
@Log
class Car {
Guarded Car() {
w/ an if log.info 'Car constructed'
}
}
def c = new Car()
31
mercredi 18 mai 2011
82. @Log
• Four different loggers can be injected
– @Log, @Commons, @Log4j, @Slf4j
• Possible to implement your own strategy
import groovy.util.logging.*
Hackerg
@Log arten
class Car { certified!
Guarded Car() {
w/ an if log.info 'Car constructed'
}
}
def c = new Car()
31
mercredi 18 mai 2011
83. @Field
• Surprising scoping rules in scripts
– variables are local to the run() method
– variables aren’t visible in methods
•although visually the variable is in a surrounding scope
• @Field creates a field in the script class
@Field List awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6
32
mercredi 18 mai 2011
84. Controlling code execution
• Your application may run user’s code
– what if the code runs in infinite loops or for too long?
– what if the code consumes too many resources?
33
mercredi 18 mai 2011
85. Controlling code execution
• Your application may run user’s code
– what if the code runs in infinite loops or for too long?
– what if the code consumes too many resources?
• 3 new transforms at your rescue
– @ThreadInterrupt: adds Thread#isInterrupted checks
so your executing thread stops when interrupted
– @TimedInterrupt: adds checks in method and closure
bodies to verify it’s run longer than expected
– @ConditionalInterrupt: adds checks with your own
conditional logic to break out from the user code
33
mercredi 18 mai 2011
86. Controlling code execution
• Your application may run user’s code
– what if the code runs in infinite loops or for too long?
– what if the code consumes too many resources?
• 3 new transforms at your rescue
– @ThreadInterrupt: adds Thread#isInterrupted checks
so your executing thread stops when interrupted
– @TimedInterrupt: adds checks in method and closure
bodies to verify it’s run longer than expected
– @ConditionalInterrupt: adds checks with your own
conditional logic to break out from the user code
33
mercredi 18 mai 2011
87. Controlling code execution
• Your application may run user’s code
– what if the code runs in infinite loops or for too long?
– what if the code consumes too many resources?
• 3 new transforms at your rescue
– @ThreadInterrupt: adds Thread#isInterrupted checks
so your executing thread stops when interrupted
– @TimedInterrupt: adds checks in method and closure
bodies to verify it’s run longer than expected
– @ConditionalInterrupt: adds checks with your own
conditional logic to break out from the user code
• Also see compilation customizers later on
33
mercredi 18 mai 2011
88. @ThreadInterrupt
@ThreadInterrupt
import groovy.transform.ThreadInterrupt
while (true) {
// eat lots of CPU
}
34
mercredi 18 mai 2011
89. @ThreadInterrupt
@ThreadInterrupt
import groovy.transform.ThreadInterrupt
while (true) {
{ if (Thread.currentThread.isInterrupted())
throw new InterruptedException() }
// eat lots of CPU
}
34
mercredi 18 mai 2011
90. @ThreadInterrupt
@ThreadInterrupt
import groovy.transform.ThreadInterrupt
while (true) {
{ if (Thread.currentThread.isInterrupted())
throw new InterruptedException() }
// eat lots of CPU
}
• Two optional annotation parameters available
– checkOnMethodStart (true by default)
– applyToAllClasses (true by default)
34
mercredi 18 mai 2011
91. @TimedInterrupt
@TimedInterrupt(10)
import groovy.transform.TimedInterrupt
while (true) {
// eat lots of CPU
}
• InterruptedException thrown when checks indicate
code ran longer than desired
• Optional annotation parameters available
– same as @ThreadInterrupt
– value: for an amount of time duration
– unit: for the time duration unit (TimeUnit.SECONDS)
35
mercredi 18 mai 2011
92. @ConditionalInterrupt
• Specify your own condition to be inserted
at the start of method and closure bodies
– check for available resources, number of times run, etc.
• Leverages the new closure annotation parameter
feature of Groovy 1.8
@ConditionalInterrupt({ counter++ > 2 })
import groovy.transform.ConditionalInterrupt
import groovy.transform.Field
@Field int counter = 0
100.times {
println 'executing script method...'
}
36
mercredi 18 mai 2011
93. @ToString
• Provides a default toString() method to your types
• Available annotation options
– includeNames, includeFields, includeSuper, excludes
import groovy.transform.ToString
@ToString
class Person {
String name
int age
}
println new Person(name: 'Pete', age: 15)
// => Person(Pete, 15)
37
mercredi 18 mai 2011
94. @EqualsAndHashCode
• Provides default implementations for equals() and
hashCode() methods
import groovy.transform.EqualsAndHashCode
@EqualsAndHashCode
class Coord {
int x, y
}
def c1 = new Coord(x: 20, y: 5)
def c2 = new Coord(x: 20, y: 5)
assert c1 == c2
assert c1.hashCode() == c2.hashCode()
38
mercredi 18 mai 2011
95. @TupleConstructor
• Provides a «classical» constructor with all properties
• Several annotation parameter options available
import groovy.transform.TupleConstructor
@TupleConstructor
class Person {
String name
int age
}
def m = new Person('Marion', 3)
assert m.name == 'Marion'
assert m.age == 3
39
mercredi 18 mai 2011
96. @Canonical
• One annotation to rule them all!
– @Canonical mixes together
•@ToString
•@EqualsAndHashCode
•@TupleConstructor
• You can customize behavior by combining
@Canonical and one of the other annotations
40
mercredi 18 mai 2011
97. @InheritConstructor
• Classes like Exception are painful when extended,
as all the base constructors should be replicated
class CustomException extends Exception {
CustomException() { super() }
CustomException(String msg) { super(msg) }
CustomException(String msg, Throwable t) { super(msg, t) }
CustomException(Throwable t) { super(t) }
}
41
mercredi 18 mai 2011
98. @InheritConstructor
• Classes like Exception are painful when extended,
as all the base constructors should be replicated
import groovy.transform.*
@InheritConstructors
class CustomException extends Exception {
CustomException() { super() }
CustomException(String msg) { super(msg) }
CustomException(String msg, Throwable t) { super(msg, t) }
CustomException(Throwable t) { super(t) }
}
41
mercredi 18 mai 2011
99. @WithReadLock, @WithWriteLock
import groovy.transform.*
class ResourceProvider {
private final Map<String, String> data = new HashMap<>()
@WithReadLock
String getResource(String key) {
return data.get(key)
}
@WithWriteLock
void refresh() {
//reload the resources into memory
}
}
42
mercredi 18 mai 2011
100. @WithReadLock, @WithWriteLock
import groovy.transform.*
class ResourceProvider {
private final Map<String, String> data = new HashMap<>()
{ @WithReadLock
String getResource(String key) {
return data.get(key)
}
{ @WithWriteLock
void refresh() {
//reload the resources into memory
}
}
42
mercredi 18 mai 2011
101. Miscelanous
• Compilation customizers
• Java 7 diamond operator
• Slashy and dollar slashy strings
• New GDK methods
• (G)String to Enum coercion
43
mercredi 18 mai 2011
102. Compilation customizers
• Ability to apply some customization to the Groovy
compilation process
• Three available customizers
– ImportCustomizer
– SecureASTCustomizer
– ASTTransformationCustomizer
• But you can implement your own
44
mercredi 18 mai 2011
103. Imports customizer
def configuration = new CompilerConfiguration()
def custo = new ImportCustomizer()
custo.addStaticStar(Math.name)
configuration.addCompilationCustomizers(custo)
def result = new GroovyShell(configuration)
.evaluate(" cos PI/3 ")
45
mercredi 18 mai 2011
104. Applying an AST transformation
def configuration = new CompilerConfiguration()
configuration.addCompilationCustomizers(
new ASTTransformationCustomizer(Log))
new GroovyShell(configuration).evaluate("""
class Car {
Car() {
log.info 'Car constructed'
}
}
log.info 'Constructing a car'
def c = new Car()
""")
46
mercredi 18 mai 2011
105. Secure AST customizer
Idea: Implement an «arithmetic shell»
Being able control what a user script is
allowed to do: only arithmetic expressions
• Let’s setup our environment
– some imports
– an import customizer to import java.lang.Math.*
– prepare a secure AST customizer
import org.codehaus.groovy.control.customizers.*
import org.codehaus.groovy.control.*
import static org.codehaus.groovy.syntax.Types.*
def imports = new ImportCustomizer().addStaticStars('java.lang.Math')
def secure = new SecureASTCustomizer()
...
47
mercredi 18 mai 2011
106. Secure AST customizer
...
secure.with {
// disallow closure creation
closuresAllowed = false
// disallow method definitions
methodDefinitionAllowed = false
// empty white list => forbid imports
importsWhitelist = []
staticImportsWhitelist = []
// only allow the java.lang.Math.* static import
staticStarImportsWhitelist = ['java.lang.Math'
...
48
mercredi 18 mai 2011
107. Secure AST customizer
...
// language tokens allowed
tokensWhitelist = [
PLUS, MINUS, MULTIPLY, DIVIDE, MOD, POWER, PLUS_PLUS,
MINUS_MINUS, COMPARE_EQUAL, COMPARE_NOT_EQUAL,
COMPARE_LESS_THAN, COMPARE_LESS_THAN_EQUAL,
COMPARE_GREATER_THAN, COMPARE_GREATER_THAN_EQUAL
]
// types allowed to be used (including primitive types)
constantTypesClassesWhiteList = [
Integer, Float, Long, Double, BigDecimal,
Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE
]
// classes who are allowed to be receivers of method calls
receiversClassesWhiteList = [
Math, Integer, Float, Double, Long, BigDecimal ]
}
...
49
mercredi 18 mai 2011
108. Secure AST customizer
• Ready to evaluate our arithmetic expressions!
...
def config = new CompilerConfiguration()
config.addCompilationCustomizers(imports, secure)
def shell = new GroovyShell(config)
shell.evaluate 'cos(PI/3)'
• But the following would have failed:
shell.evaluate 'System.exit(0)'
50
mercredi 18 mai 2011
109. Slashy and dollar slashy strings
• Slashy strings are now multiline
– particularly handy for multi-line regexs
• Dollar slashy string notation introduced
– a multiline GString with different escaping rules
def (name, date) = ["Guillaume", "May, 17th"]
def dollarSlashy = $/
Hello $name, today we're ${date}
$ dollar‐sign
$$ dollar‐sign
backslash
/ slash
$/ slash
/$
51
mercredi 18 mai 2011
111. New GDK methods
// count
assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5
52
mercredi 18 mai 2011
112. New GDK methods
// count
assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5
// count by
assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 }
assert [(true):2, (false):4]
== 'Groovy'.toList().countBy{ it == 'o' }
52
mercredi 18 mai 2011
113. New GDK methods
// count
assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5
// count by
assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 }
assert [(true):2, (false):4]
== 'Groovy'.toList().countBy{ it == 'o' }
// min/max for maps with closures
def map = [a: 1, bbb: 4, cc: 5, dddd: 2]
assert map.max { it.key.size() }.key == 'dddd'
assert map.min { it.value }.value == 1
52
mercredi 18 mai 2011
114. New GDK methods
// count
assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5
// count by
assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 }
assert [(true):2, (false):4]
== 'Groovy'.toList().countBy{ it == 'o' }
// min/max for maps with closures
def map = [a: 1, bbb: 4, cc: 5, dddd: 2]
assert map.max { it.key.size() }.key == 'dddd'
assert map.min { it.value }.value == 1
// map withDefault()
def words = "one two two three three three".split()
def freq = [:].withDefault { k ‐> 0 }
words.each { freq[it] += 1 }
52
mercredi 18 mai 2011
115. (G)String to Enum coercion
enum Color {
red, green, blue
}
53
mercredi 18 mai 2011
116. (G)String to Enum coercion
enum Color {
red, green, blue
}
53
mercredi 18 mai 2011
117. (G)String to Enum coercion
enum Color {
red, green, blue
}
// coercion with as
def r = "red" as Color
53
mercredi 18 mai 2011
118. (G)String to Enum coercion
enum Color {
red, green, blue
}
// coercion with as
def r = "red" as Color
// implicit coercion
Color b = "blue"
53
mercredi 18 mai 2011
119. (G)String to Enum coercion
enum Color {
red, green, blue
}
// coercion with as
def r = "red" as Color
// implicit coercion
Color b = "blue"
// with GStrings too
def g = "${'green'}" as Color
53
mercredi 18 mai 2011
121. Groovy 1.9 roadmap
• Java 7 alignements: Project Coin
– binary literals
– underscore in literals
– multicatch
• JDK 7: InvokeDynamic
• Towards a more modular Groovy
• Rewritten Antlr 3 grammar (GSoC)
• Eclipse compiler to replace
the joint compiler?
• What else? Your call!
55
mercredi 18 mai 2011
122. Groovy 1.9 roadmap
• Java 7 alignements: Project Coin
– binary literals
– underscore in literals
– multicatch
• JDK 7: InvokeDynamic
• Towards a more modular Groovy
• Rewritten Antlr 3 grammar (GSoC)
• Eclipse compiler to replace
the joint compiler?
• What else? Your call!
55
mercredi 18 mai 2011
123. Binary literals
• We had decimal, octal and hexadecimal notations
for number literals
• We can now use binary representations too
int x = 0b10101111
assert x == 175
byte aByte = 0b00100001
assert aByte == 33
int anInt = 0b1010000101000101
assert anInt == 41285
56
mercredi 18 mai 2011
124. Underscore in literals
• We can now also add underscores
in number literals for more readability
long creditCardNumber = 1234_5678_9012_3456L
long socialSecurityNumbers = 999_99_9999L
float monetaryAmount = 12_345_132.12
long hexBytes = 0xFF_EC_DE_5E
long hexWords = 0xFFEC_DE5E
long maxLong = 0x7fff_ffff_ffff_ffffL
long alsoMaxLong = 9_223_372_036_854_775_807L
long bytes = 0b11010010_01101001_10010100_10010010
57
mercredi 18 mai 2011
125. Multicatch
• One block for multiple exception caught
– rather than duplicating the block
try {
/* ... */
} catch(IOException | NullPointerException e) {
/* one block to treat 2 exceptions */
}
58
mercredi 18 mai 2011