• Save
Lambdas and Generics (long version) - Bordeaux/Toulouse JUG
Upcoming SlideShare
Loading in...5
×
 

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

on

  • 1,093 views

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

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.

Statistics

Views

Total Views
1,093
Views on SlideShare
1,086
Embed Views
7

Actions

Likes
0
Downloads
12
Comments
0

1 Embed 7

https://twitter.com 7

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

  • 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
  • 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
  • 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"); Collector<Tweet, ?, Map<Boolean, List<Tweet>>> collector = Collectors.partitioningBy(lambda); return stream.collect(collector);
  • 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);
  • 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 safety: Unchecked cast from List<capture#1-of ?> to List<String> 19
  • 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> l = new ArrayList<Integer>(); // Illegal 24
  • 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
  • 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 27
  • 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
  • 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 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
  • 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
  • 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
  • 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 38
  • Trick #1 Determine the return value type Artificially give the type with a dedicated parameter <T> T anyObject(Class<T> clazz) 39
  • But how to pass a generic? public void foo(String s) public void foo(Object o) foo(anyObject(List<String>.class)); Illegal 40
  • Some solutions This would work foo((String) anyObject()); foo((List<String>) anyObject()); // Warning But still doesn’t work for generics 41
  • 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
  • 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));
  • 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(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");
  • Trick #3: Lambda inference Object o = (Runnable) () -> { System.out.println("hi"); }; Collections.sort(strings, (String a, String b) -> a.compareTo(b));
  • Erasure 47
  • 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 } }
  • … 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
  • 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
  • Useful! class A {} abstract class BaseDao<T> { public T load(final long id) { // … } } class ADao extends BaseDao<A> {} © OCTO 2011 51
  • 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
  • Bridge © OCTO 2011 53
  • 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; } }
  • 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.ClassCastException
  • 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
  • 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
  • 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 on lambda: http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html Everything on generics: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
  • Conclusion Questions? http://perfug.github.io/ +Henri @henritremblay htr@octo.com © OCTO 2011 http://brownbaglunch.fr 61