Les lambda arrivent!
En attendant, êtes-vous sûr d'avoir
compris les génériques?
Henri Tremblay
Architecte Senior
OCTO Tec...
Les lambda arrivent!
En attendant, êtes-vous sûr d'avoir
compris les génériques?
Henri Tremblay
Architecte Senior
OCTO Tec...
Henri Tremblay
OCTO Technology
Responsable R&D
Performance
Calcul parallèle

Open Source
EasyMock
Objenesis
September 2013
September 2013
March 2014
March 2014
September 2004
Lambda

return Tweet.TWEETS.stream()
.collect(Collectors
.partitioningBy(
t->t.containsHashTag("#lambda")));
Lambda = Fun with generics
Stream<Tweet> stream = Tweet.TWEETS.stream();
Predicate<Tweet> lambda = t -> t.containsHashTag(...
Lambda = Fun with generics
Stream<Tweet> stream = Tweet.TWEETS.stream();
Function<Tweet, Boolean> lambda = t -> t.contains...
What do I need to know?
Why

© OCTO 2011

12
What do I need to know?
Why

Covariance

© OCTO 2011

13
What do I need to know?
Why

Covariance
Capture

© OCTO 2011

14
What do I need to know?
Why

Covariance
Capture
Inference
© OCTO 2011

15
What do I need to know?
Why

Covariance
Capture
Inference
Erasure
© OCTO 2011

16
What do I need to know?
Why

Covariance

Capture

Erasure
© OCTO 2011

Inference

Bridge
17
Faire compiler

18
Dreaded warnings
Type safety: The expression of type List needs
unchecked conversion to conform to List<String>

Type safe...
Ostrich defense
@SuppressWarnings("unchecked")

20
Why

© OCTO 2011

21

27 au 29 mars 2013
Rule #1

A code compiling
without warning should
never ever cause a
ClassCastException
22
Covariance

23

27 au 29 mars 2013
Arrays
Arrays are covariant:
Number n = Integer.MAX_VALUE;
Number[] list = new Integer[0];
Generics are not:
List<Number> ...
Why not?
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));
int i = ...
Why for array?
Integer[] list = // ...
foo(list);

public void foo(Object[] o) {
// ...
}
Arrays and generics don’t mix well
Can’t have an array of generics
List<String>[] lsa = new List<String>[10];// illegal

2...
Because
If it was allowed
List<String>[] lsa = new List<String>[10]; // illegal
Object[] oa = lsa; // OK (covariant)
oa[0]...
Exception

List<?>[] l = new ArrayList<?>[3];

29
Capture

30

27 au 29 mars 2013
Capture usually is
Type
List<?> bar();
<T> IExpectationSetters<T> expect(T value);
void andReturn(T value); // Method of I...
Detail
List<?> bar();
<T> IExpectationSetters<T> expect(T value);
void andReturn(T value);
expect(bar()).andReturn(new Arr...
Only solution
We need to cast
expect((List<String>) bar()).andReturn(new
Tell to expect we want a
ArrayList<String>());
Li...
Inference

34
Diamonds are a programmer best friend
List<String> l = new ArrayList<>();
How the compiler tells the type
Determine
the return
value type

The parameter

<T> T anyObject(T clazz)

36
How the compiler tells the type
The assigned
variable

Determine the
return type

MyType var = <T> T anyObject()

37
But watch out with overloading
public void foo(String s)
public void foo(Object o)

foo(anyObject());
Can’t
guess the
type...
Trick #1
Determine the return
value type

Artificially give the type with a
dedicated parameter

<T> T anyObject(Class<T> ...
But how to pass a generic?
public void foo(String s)
public void foo(Object o)

foo(anyObject(List<String>.class));

Illeg...
Some solutions
This would work

foo((String) anyObject());
foo((List<String>) anyObject()); // Warning
But still doesn’t w...
Trick #2
So the only solution is
foo(EasyMock.<List<String>> anyObject());

… which sadly doesn’t support static imports
f...
Trick #2 applied to Lambda
Return type: Map<Boolean, List<Tweet>>
return Tweet.TWEETS.stream()
.collect( Collectors.<Tweet...
Lambda = Inference
return Tweet.TWEETS.stream()
.collect(Collectors
.partitioningBy(
t->t.containsHashTag("#lambda"));
How did he do it?
List<Tweet> list = Tweet.TWEETS;
Stream<Tweet> stream = list.stream();
R result = stream.collect(Collect...
Trick #3: Lambda inference

Object o = (Runnable) () -> {
System.out.println("hi");
};

Collections.sort(strings,
(String ...
Erasure

47
Erasure…
public void foo() {
List<String> l = new ArrayList<String>();

for (String s : l) {

No type

System.out.println(...
… or not erasure
public class A extends ArrayList<String> {}

public static void main(final String[] args) {
Parameterized...
Type class
java.lang.reflect.Type
•
•
•
•
•

GenericArrayType
ParameterizedType
TypeVariable
WildcardType
Implemented by C...
Useful!
class A {}

abstract class BaseDao<T> {
public T load(final long id) {
// …
}
}
class ADao extends BaseDao<A> {}
©...
Useful!
@SuppressWarnings("unchecked")
public T load(final long id) {
ParameterizedType type =
(ParameterizedType) getClas...
Bridge

© OCTO 2011

53
Everything seems normal…
class A<T> {
abstract void set(T value);
}
class B extends A<String> {
String value;
@Override
vo...
But is not
class B extends A {
void set(String value) {
this.value = value;
}
volatile void set(Object o){
set((String)o);...
Example
Raw type warning

Perfectly compiling

A a = new B();
a.set(new Object());
But at runtime:
java.lang.ClassCastExce...
The actual problem being
B.class.getDeclaredMethods()
This

Returns that

volatile void set(java.lang.Object)
void B.set(j...
What about lambdas?
public class A {
public static void main(String[] args) {
Method[] methods = A.class.getDeclaredMethod...
Conclusion

Who has learned
something today?

© OCTO 2011

59
Useful links
Nice lambda tutorial (in French):
http://lambda.ninjackaton.ninja-squad.com/

Description of inference types ...
Conclusion

Questions?

http://perfug.github.io/

+Henri
@henritremblay
htr@octo.com
© OCTO 2011

http://brownbaglunch.fr
...
Upcoming SlideShare
Loading in...5
×

Lambdas and Generics (long version) - Bordeaux/Toulouse JUG

1,071

Published on

Lambda expressions are coming soon. They promise to be a nice complexity cocktail with the 9 years old generics.

Lets go deep into the generics to get a better understanding. Mix them with lambdas and wait calmly for Java 8 to arrive.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,071
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
12
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Lambdas and Generics (long version) - Bordeaux/Toulouse JUG"

  1. 1. Les lambda arrivent! En attendant, êtes-vous sûr d'avoir compris les génériques? Henri Tremblay Architecte Senior OCTO Technology @henri_tremblay 27 au 29 mars 2013
  2. 2. Les lambda arrivent! En attendant, êtes-vous sûr d'avoir compris les génériques? Henri Tremblay Architecte Senior OCTO Technology @henri_tremblay 27 au 29 mars 2013
  3. 3. Henri Tremblay OCTO Technology Responsable R&D Performance Calcul parallèle Open Source EasyMock Objenesis
  4. 4. September 2013
  5. 5. September 2013
  6. 6. March 2014
  7. 7. March 2014
  8. 8. September 2004
  9. 9. Lambda return Tweet.TWEETS.stream() .collect(Collectors .partitioningBy( t->t.containsHashTag("#lambda")));
  10. 10. Lambda = Fun with generics Stream<Tweet> stream = Tweet.TWEETS.stream(); Predicate<Tweet> lambda = t -> t.containsHashTag("#lambda"); Collector<Tweet, ?, Map<Boolean, List<Tweet>>> collector = Collectors.partitioningBy(lambda); return stream.collect(collector);
  11. 11. Lambda = Fun with generics Stream<Tweet> stream = Tweet.TWEETS.stream(); Function<Tweet, Boolean> lambda = t -> t.containsHashTag("#lambda"); Collector<Tweet, Map<Boolean, List<Tweet>>> collector = Collectors.<Tweet, Boolean, List<Tweet>, Map<Boolean, List<Tweet>>> groupingBy(lambda, HashMap::new, ArrayList::new); return stream.collect(collector);
  12. 12. What do I need to know? Why © OCTO 2011 12
  13. 13. What do I need to know? Why Covariance © OCTO 2011 13
  14. 14. What do I need to know? Why Covariance Capture © OCTO 2011 14
  15. 15. What do I need to know? Why Covariance Capture Inference © OCTO 2011 15
  16. 16. What do I need to know? Why Covariance Capture Inference Erasure © OCTO 2011 16
  17. 17. What do I need to know? Why Covariance Capture Erasure © OCTO 2011 Inference Bridge 17
  18. 18. Faire compiler 18
  19. 19. Dreaded warnings Type safety: The expression of type List needs unchecked conversion to conform to List<String> Type safety: Unchecked cast from List<capture#1-of ?> to List<String> 19
  20. 20. Ostrich defense @SuppressWarnings("unchecked") 20
  21. 21. Why © OCTO 2011 21 27 au 29 mars 2013
  22. 22. Rule #1 A code compiling without warning should never ever cause a ClassCastException 22
  23. 23. Covariance 23 27 au 29 mars 2013
  24. 24. Arrays Arrays are covariant: Number n = Integer.MAX_VALUE; Number[] list = new Integer[0]; Generics are not: List<Number> l = new ArrayList<Integer>(); // Illegal 24
  25. 25. Why not? List<Integer> li = new ArrayList<Integer>(); List<Number> ln = li; // illegal ln.add(new Float(3.1415)); int i = li.get(0); // ClassCastException Would work if covariant And allow to break rule #1 25
  26. 26. Why for array? Integer[] list = // ... foo(list); public void foo(Object[] o) { // ... }
  27. 27. Arrays and generics don’t mix well Can’t have an array of generics List<String>[] lsa = new List<String>[10];// illegal 27
  28. 28. Because If it was allowed List<String>[] lsa = new List<String>[10]; // illegal Object[] oa = lsa; // OK (covariant) oa[0] = new ArrayList<Integer>(); // OK String s = lsa[0].get(0); // bad 28
  29. 29. Exception List<?>[] l = new ArrayList<?>[3]; 29
  30. 30. Capture 30 27 au 29 mars 2013
  31. 31. Capture usually is Type List<?> bar(); <T> IExpectationSetters<T> expect(T value); void andReturn(T value); // Method of IExpectationSetters expect(bar()).andReturn(new ArrayList<String>()); And you get The method andReturn(List<capture#6-of ?>) in the type IExpectationSetters<List<capture#6-of ?>> is not applicable for the arguments (ArrayList<String>) 31
  32. 32. Detail List<?> bar(); <T> IExpectationSetters<T> expect(T value); void andReturn(T value); expect(bar()).andReturn(new ArrayList<String>()); List<Capture#6> bar = bar(); IExpectationSetters<List<Capture#6>> es = expect(bar()); es.andReturn(List<Capture#6> value); 32
  33. 33. Only solution We need to cast expect((List<String>) bar()).andReturn(new Tell to expect we want a ArrayList<String>()); List<String> But still a warning Type safety: Unchecked cast from List<capture#6-of ?> to List<String> Framework coder tip: Try to never return a wildcard unless necessary 33
  34. 34. Inference 34
  35. 35. Diamonds are a programmer best friend List<String> l = new ArrayList<>();
  36. 36. How the compiler tells the type Determine the return value type The parameter <T> T anyObject(T clazz) 36
  37. 37. How the compiler tells the type The assigned variable Determine the return type MyType var = <T> T anyObject() 37
  38. 38. But watch out with overloading public void foo(String s) public void foo(Object o) foo(anyObject()); Can’t guess the type 38
  39. 39. Trick #1 Determine the return value type Artificially give the type with a dedicated parameter <T> T anyObject(Class<T> clazz) 39
  40. 40. But how to pass a generic? public void foo(String s) public void foo(Object o) foo(anyObject(List<String>.class)); Illegal 40
  41. 41. Some solutions This would work foo((String) anyObject()); foo((List<String>) anyObject()); // Warning But still doesn’t work for generics 41
  42. 42. Trick #2 So the only solution is foo(EasyMock.<List<String>> anyObject()); … which sadly doesn’t support static imports foo(.<List<String>> anyObject()); // Illegal 42
  43. 43. Trick #2 applied to Lambda Return type: Map<Boolean, List<Tweet>> return Tweet.TWEETS.stream() .collect( Collectors.<Tweet, Boolean, List<Tweet>, Map<Boolean, List<Tweet>>> groupingBy(t->t.containsHashTag("#lambda"), HashMap::new, ArrayList::new));
  44. 44. Lambda = Inference return Tweet.TWEETS.stream() .collect(Collectors .partitioningBy( t->t.containsHashTag("#lambda"));
  45. 45. How did he do it? List<Tweet> list = Tweet.TWEETS; Stream<Tweet> stream = list.stream(); R result = stream.collect(Collector<? super T, ?, R> collector); R result = stream.collect(Collector<? super Tweet, ?, R> collector); Collector<T, ?, Map<Boolean, List<T>>> collector = Collectors.partitioningBy(Predicate<? super T> predicate); Collector<Tweet, ?, Map<Boolean, List<Tweet>>> collector = Collectors.partitioningBy(Predicate<? super Tweet> predicate); Map<Boolean, List<Tweet>> result = stream.collect(Collector<? super Tweet, ?, Map<Boolean, List<Tweet>>> collector); Predicate<? super Tweet> lambda = (Tweet t) -> t.containsHashTag("#lambda");
  46. 46. Trick #3: Lambda inference Object o = (Runnable) () -> { System.out.println("hi"); }; Collections.sort(strings, (String a, String b) -> a.compareTo(b));
  47. 47. Erasure 47
  48. 48. Erasure… public void foo() { List<String> l = new ArrayList<String>(); for (String s : l) { No type System.out.println(s); } public void foo() { } List l = new ArrayList(); for (String s : l) { System.out.println(s); Compilation } }
  49. 49. … or not erasure public class A extends ArrayList<String> {} public static void main(final String[] args) { ParameterizedType type = (ParameterizedType) A.class.getGenericSuperclass(); System.out.println( type.getActualTypeArguments()[0]); }  prints class java.lang.String 49
  50. 50. Type class java.lang.reflect.Type • • • • • GenericArrayType ParameterizedType TypeVariable WildcardType Implemented by Class New powers unleashed! java.lang.reflect.GenericDeclaration Implemented by Class, Method, Constructor 50
  51. 51. Useful! class A {} abstract class BaseDao<T> { public T load(final long id) { // … } } class ADao extends BaseDao<A> {} © OCTO 2011 51
  52. 52. Useful! @SuppressWarnings("unchecked") public T load(final long id) { ParameterizedType type = (ParameterizedType) getClass() .getGenericSuperclass(); ADao BaseDao<A> A Type actualType = type.getActualTypeArguments()[0]; return em.find((Class<T>) actualType, (Long) id); } Unsafe cast
  53. 53. Bridge © OCTO 2011 53
  54. 54. Everything seems normal… class A<T> { abstract void set(T value); } class B extends A<String> { String value; @Override void set(final String value) { this.value = value; } }
  55. 55. But is not class B extends A { void set(String value) { this.value = value; } volatile void set(Object o){ set((String)o); } }
  56. 56. Example Raw type warning Perfectly compiling A a = new B(); a.set(new Object()); But at runtime: java.lang.ClassCastException
  57. 57. The actual problem being B.class.getDeclaredMethods() This Returns that volatile void set(java.lang.Object) void B.set(java.lang.String) And gives you no way to find out which method is bridged
  58. 58. What about lambdas? public class A { public static void main(String[] args) { Method[] methods = A.class.getDeclaredMethods(); Arrays.stream(methods).forEach(m -> System.out.println(m + " " + m.isBridge() + " " + m.isSynthetic())); } } Prints this public static void A.main(java.lang.String[]) false false private static void A.lambda$0(java.lang.reflect.Method) false true
  59. 59. Conclusion Who has learned something today? © OCTO 2011 59
  60. 60. Useful links Nice lambda tutorial (in French): http://lambda.ninjackaton.ninja-squad.com/ Description of inference types on lambda: http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html Everything on generics: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
  61. 61. Conclusion Questions? http://perfug.github.io/ +Henri @henritremblay htr@octo.com © OCTO 2011 http://brownbaglunch.fr 61

×