Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
27 au 29 mars 2013
Java 8, Lambdas, Generics:
How to survive?
Henri Tremblay
Java Champion
tremblay.pro inc.
@henri_trembl...
Loves
IT Strategy
Performance
Productivity
Great food!
Do Open Source
Henri Tremblay
Try to be useful
September 2004
March 18 2014
Java 7 End of Life
Java 8 support
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(...
What do I need to know?
9© OCTO 2011
Why
What do I need to know?
10© OCTO 2011
Why
Covariance
What do I need to know?
11© OCTO 2011
Why
Covariance
Capture
What do I need to know?
12© OCTO 2011
Why
Covariance
Capture
Inference
What do I need to know?
13© OCTO 2011
Why
Covariance
Capture
Inference
Erasure
What do I need to know?
14© OCTO 2011
Why Covariance
Capture Inference
Erasure Bridge
Compiled successfully!
15
Dreaded warnings
16
Type safety: The expression of type List needs
unchecked conversion to conform to List<String>
Type sa...
Ostrich defense
@SuppressWarnings("unchecked")
17
27 au 29 mars 2013
Why
18© OCTO 2011
Rule #1
A code compiling
without warning should
never ever cause a
ClassCastException
19
27 au 29 mars 2013
Covariance
20
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
24
Exception
List<?>[] l = new ArrayList<?>[3];
25
Because
If it was allowed
List<String>[] lsa = new List<String>[10]; // illegal
Object[] oa = lsa; // OK (covariant)
oa[0]...
27 au 29 mars 2013
Capture
27
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
ArrayList<String>());
But still a warning
Type sa...
Inference
31
Diamonds are a programmer best friend
List<String> l = new ArrayList<>();
How the compiler tells the type
<T> T anyObject(T clazz)
33
The parameterDetermine
the return
value type
How the compiler tells the type
MyType var = <T> T anyObject()
34
Determine the
return type
The assigned
variable
But watch out with overloading
public void foo(String s)
public void foo(Object o)
foo(anyObject());
35
Can’t
guess the
ty...
Trick #1
<T> T anyObject(Class<T> clazz)
36
Artificially give the type with a
dedicated parameter
Determine the return
val...
But how to pass a generic?
public void foo(String s)
public void foo(Object o)
foo(anyObject(List<String>.class));
37
Ille...
Some solutions
foo((String) anyObject());
foo((List<String>) anyObject()); // Warning
38
This would work
But still doesn’t...
Trick #2
So the only solution is
foo(EasyMock.<List<String>> anyObject());
… which sadly doesn’t support static imports
fo...
Trick #2 applied to Lambda
return Tweet.TWEETS.stream()
.collect( Collectors.<Tweet, Boolean,
List<Tweet>, Map<Boolean, Li...
Lambda = Inference
return Tweet.TWEETS.stream()
.collect(Collectors
.partitioningBy(
t->t.containsHashTag("#lambda"));
How did it do it?
Tweet.TWEETS.stream()
List<Tweet> list = Tweet.TWEETS;
Stream<Tweet> stream = list.stream();
How did it do it?
Stream<Tweet> stream = list.stream();
R result = stream.collect(Collector<? super T, ?, R> collector);
R...
How did it do it?
stream.collect(Collector<? super Tweet, ?, R> collector);
Collector<T, ?, Map<Boolean, List<T>>> collect...
How did it do it?
Predicate<? super Tweet> lambda = t -> t.containsHashTag("#lambda");
We now know that
So the best t can ...
Trick #3: Lambda inference
Object o = (Runnable) () -> {
System.out.println("hi");
};
Collections.sort(strings,
(String a,...
Erasure
47
Erasure…
public void foo() {
List<String> l = new ArrayList<String>();
for (String s : l) {
System.out.println(s);
}
}
No ...
… or not erasure
public class A extends ArrayList<String> {}
public static void main(final String[] args) {
ParameterizedT...
Type class
java.lang.reflect.Type
• GenericArrayType
• ParameterizedType
• TypeVariable
• WildcardType
• Implemented by Cl...
Useful!
class A {}
abstract class BaseDao<T> {
public T load(final long id) {
// …
}
}
class ADao extends BaseDao<A> {}
51...
Useful!
@SuppressWarnings("unchecked")
public T load(final long id) {
ParameterizedType type =
(ParameterizedType) getClas...
Bridge
53© OCTO 2011
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
A a = new B();
a.set(new Object());
But at runtime:
java.lang.ClassCastException
Raw type warning Perfectly compil...
The actual problem being
B.class.getDeclaredMethods()
volatile void set(java.lang.Object)
void B.set(java.lang.String)
Thi...
What about lambdas?
public class A {
public static void main(String[] args) {
Method[] methods = A.class.getDeclaredMethod...
Conclusion
Who has learned
something today?
59© OCTO 2011
Useful links
Nice lambda tutorial (in French):
http://lambda.ninjackaton.ninja-squad.com/
Description of inference types o...
Conclusion
Questions?
61© OCTO 2011
http://www.montreal-
jug.org/
http://brownbaglunch.fr
@henri_tremblay
http://blog.trem...
Prochain SlideShare
Chargement dans…5
×

Java 8, lambdas, generics: How to survive? - NYC Java Meetup Group

716 vues

Publié le

Lambdas are sexy. But they are adding complexity. Mixed with generics, it creates a dangerous cocktail. Together, we will start from the bottom of generics and go straight through lambda inference. To explain why it is the way it is and tell you how to survive.

Publié dans : Logiciels
  • Soyez le premier à commenter

Java 8, lambdas, generics: How to survive? - NYC Java Meetup Group

  1. 1. 27 au 29 mars 2013 Java 8, Lambdas, Generics: How to survive? Henri Tremblay Java Champion tremblay.pro inc. @henri_tremblay http://blog.tremblay.pro NYC Java Meetup Group
  2. 2. Loves IT Strategy Performance Productivity Great food! Do Open Source Henri Tremblay Try to be useful
  3. 3. September 2004
  4. 4. March 18 2014
  5. 5. Java 7 End of Life
  6. 6. Java 8 support
  7. 7. Lambda return Tweet.TWEETS.stream() .collect(Collectors .partitioningBy( t->t.containsHashTag("#lambda")));
  8. 8. 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);
  9. 9. What do I need to know? 9© OCTO 2011 Why
  10. 10. What do I need to know? 10© OCTO 2011 Why Covariance
  11. 11. What do I need to know? 11© OCTO 2011 Why Covariance Capture
  12. 12. What do I need to know? 12© OCTO 2011 Why Covariance Capture Inference
  13. 13. What do I need to know? 13© OCTO 2011 Why Covariance Capture Inference Erasure
  14. 14. What do I need to know? 14© OCTO 2011 Why Covariance Capture Inference Erasure Bridge
  15. 15. Compiled successfully! 15
  16. 16. Dreaded warnings 16 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>
  17. 17. Ostrich defense @SuppressWarnings("unchecked") 17
  18. 18. 27 au 29 mars 2013 Why 18© OCTO 2011
  19. 19. Rule #1 A code compiling without warning should never ever cause a ClassCastException 19
  20. 20. 27 au 29 mars 2013 Covariance 20
  21. 21. Arrays Arrays are covariant: Number n = Integer.MAX_VALUE; Number[] list = new Integer[0]; Generics are not: List<Number> l = new ArrayList<Integer>(); // Illegal 21
  22. 22. 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 22 Would work if covariant And allow to break rule #1
  23. 23. Why for array? Integer[] list = // ... foo(list); public void foo(Object[] o) { // ... }
  24. 24. Arrays and generics don’t mix well Can’t have an array of generics List<String>[] lsa = new List<String>[10];// illegal 24
  25. 25. Exception List<?>[] l = new ArrayList<?>[3]; 25
  26. 26. Because If it was allowed List<String>[] lsa = new List<String>[10]; // illegal Object[] oa = lsa; // OK (covariant) oa[0] = new ArrayList<Integer>(); // OK oa[0].add(42); String s = lsa[0].get(0); // bad 26
  27. 27. 27 au 29 mars 2013 Capture 27
  28. 28. 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>) 28
  29. 29. 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); 29
  30. 30. Only solution We need to cast expect((List<String>) bar()).andReturn(new ArrayList<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 30 Tell to expect we want a List<String>
  31. 31. Inference 31
  32. 32. Diamonds are a programmer best friend List<String> l = new ArrayList<>();
  33. 33. How the compiler tells the type <T> T anyObject(T clazz) 33 The parameterDetermine the return value type
  34. 34. How the compiler tells the type MyType var = <T> T anyObject() 34 Determine the return type The assigned variable
  35. 35. But watch out with overloading public void foo(String s) public void foo(Object o) foo(anyObject()); 35 Can’t guess the type
  36. 36. Trick #1 <T> T anyObject(Class<T> clazz) 36 Artificially give the type with a dedicated parameter Determine the return value type
  37. 37. But how to pass a generic? public void foo(String s) public void foo(Object o) foo(anyObject(List<String>.class)); 37 Illegal
  38. 38. Some solutions foo((String) anyObject()); foo((List<String>) anyObject()); // Warning 38 This would work But still doesn’t work for generics
  39. 39. Trick #2 So the only solution is foo(EasyMock.<List<String>> anyObject()); … which sadly doesn’t support static imports foo(.<List<String>> anyObject()); // Illegal 39
  40. 40. Trick #2 applied to Lambda return Tweet.TWEETS.stream() .collect( Collectors.<Tweet, Boolean, List<Tweet>, Map<Boolean, List<Tweet>>> groupingBy(t->t.containsHashTag("#lambda"), HashMap::new, ArrayList::new)); Return type: Map<Boolean, List<Tweet>>
  41. 41. Lambda = Inference return Tweet.TWEETS.stream() .collect(Collectors .partitioningBy( t->t.containsHashTag("#lambda"));
  42. 42. How did it do it? Tweet.TWEETS.stream() List<Tweet> list = Tweet.TWEETS; Stream<Tweet> stream = list.stream();
  43. 43. How did it do it? Stream<Tweet> stream = list.stream(); R result = stream.collect(Collector<? super T, ?, R> collector); R result = stream.collect(Collector<? super Tweet, ?, R> collector);
  44. 44. How did it do it? 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);
  45. 45. How did it do it? Predicate<? super Tweet> lambda = t -> t.containsHashTag("#lambda"); We now know that So the best t can be is a Tweet 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) { System.out.println(s); } } No type 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 java.lang.reflect.GenericDeclaration Implemented by Class, Method, Constructor 50 New powers unleashed!
  51. 51. Useful! class A {} abstract class BaseDao<T> { public T load(final long id) { // … } } class ADao extends BaseDao<A> {} 51© OCTO 2011
  52. 52. Useful! @SuppressWarnings("unchecked") public T load(final long id) { ParameterizedType type = (ParameterizedType) getClass() .getGenericSuperclass(); Type actualType = type.getActualTypeArguments()[0]; return em.find((Class<T>) actualType, (Long) id); } ADao A BaseDao<A> Unsafe cast
  53. 53. Bridge 53© OCTO 2011
  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 A a = new B(); a.set(new Object()); But at runtime: java.lang.ClassCastException Raw type warning Perfectly compiling
  57. 57. The actual problem being B.class.getDeclaredMethods() volatile void set(java.lang.Object) void B.set(java.lang.String) This Returns that 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? 59© OCTO 2011
  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 Hopefully everything on lambdas http://www.lambdafaq.org/
  61. 61. Conclusion Questions? 61© OCTO 2011 http://www.montreal- jug.org/ http://brownbaglunch.fr @henri_tremblay http://blog.tremblay.pro henri@tremblay.pro

×