jdt embraces lambda expressions

47
8 8 Srikanth Sankaran IBM India Stephan Herrmann GK Software BETA_JAVA8

Upload: eclipse-day-india

Post on 05-Jul-2015

117 views

Category:

Technology


7 download

DESCRIPTION

JDT embraces lambda expressions

TRANSCRIPT

Page 1: JDT embraces lambda expressions

8

8

Srikanth Sankaran

IBM India

Stephan Herrmann

GK Software

BETA_JAVA8

Page 2: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 3

8Eclipse and Java™ 8

● Java 8 features available in early access builds:

– JSR308 - Type Annotations.

– JEP120 - Repeating Annotations.

– JEP118 - Method Parameter Reflection.

– JSR269 - Pluggable Annotation Processor API & javax.lang.model API enhancements for Java 8.

– Support for “code carrying” interface methods.

● Partial support for

– Lambda Expressions & Method/Constructor references

– Overload resolution & Type inference changes still evolving● had been blocked by incomplete specification until late September

Page 3: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 4

8Eclipse and Java™ 8

● IDE features available in early access builds:

– Type annotations based static null analysis● substantially complete, open issues exist

– Code completion, code selection/navigation, search engine● for completed features

– Code formatter and code “reconciler”

– IDE enablement support:● AST API's, programmatic AST rewriting API support etc

● Full fledged IDE support work in high gear:

– Early access build refreshes very soon.

● JDT team:

– 12 committers + 1 contributor + 1 GSOC student+ 2 past committers on consulting role.

Java8

Java8

Page 4: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 6

8New Kinds of Methods

● defender methods

● virtual extension methods

● static interface methods

● default methods

Page 5: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 7

8New Kinds of Methods

● Code carrying methods in interfaces:

– static methods● non-OO programming even in interfaces

– default methodsprevious names:

● defender methods● virtual extension methods

Those are only 2 kinds :)

Page 6: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 8

8Default Methods - Intention

● Intention

– support evolution of interfaces in libraries:add methods to an interface w/o breaking implementors

– still legal:

Page 7: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 9

8 Default Methods - Consequences

● Consequences

– Java 8 has multiple inheritance, sort-of

– but little help for corner cases

Rootm()

Both

Leftm()D

Rightm()D

resolve:

Page 8: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 10

8 Default Methods - Consequences

● Consequences

– Java 8 has multiple inheritance, sort-of

– but little help for corner cases

Both

Leftm()D

Rightm()

The default method m() inherited from Left conflictswith another method inherited from Right

Advice: Don't!

Default Methods - Consequences

Page 9: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 12

8Default Methods - Compatibility

● Designed for compatibility during evolution

● For the price of compatibility

– Recipe for disaster:● implement java.util.List → compile against JRE 7 → OK● upgrade to JRE 8 but compile as 1.7

– Undefined compiler behavior● 1.7 compiler cannot handle default methods (from .class)● ecj and javac differ – no plans to assimilate● depending on compiler implementation details, not specification

The type MyList<E> must implement the inherited abstract method Collection<E>.stream()

Page 10: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 13

8Default Methods - Compatibility

● Designed for compatibility during evolution

● For the price of compatibility

– Recipe for disaster:● implement java.util.List → compile against JRE 7 → OK● upgrade to JRE 8 but compile as 1.7

– Undefined compiler behavior● 1.7 compiler cannot handle default methods (from .class)● ecj and javac differ – no plans to assimilate● depending on compiler implementation details, not specification

The type MyList<E> must implement the inherited abstract method Collection<E>.stream()

Advice: Don't mix -source 1.7 & JRE8!

Page 11: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 14

8

λ(JSR 335)

Page 12: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 15

8Introducing Lambda Expressions

● Lambda Expressions, Closures, Anonymous Methods

– what is in a name ?

● A function + “captured state” (may have non-locals)

– accessible even when outside of defining lexical scope

● Theoretical framework dates back several decades:

– Lambda (1930's – Church, Lisp – 1958)

– Closure (1960's - Landin, Scheme - 1975)

– Common idiomatic device in functional programming.

● Paradigm of passing a "code block as data"

Page 13: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 16

8Java 7 Style of “Code as Data”

● Via anonymous classes

Page 14: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 17

8Java 7 Style of “Code as Data”

● Via anonymous classes

So if lambda expressions help model "code as data"

are they just old wine in a new bottle?

No!

Page 15: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 18

8Lambda Expressions

● Eliminate thorny issues with anonymous classes

– Verbose/clunky Syntax

– Scoping● anonymous classes introduce their own scopes● interplay between names in enclosing scope ↔ inherited names

– Capture● can only capture explicitly final outer locals● necessarily capture enclosing class instance (memory leaks)

● Lambdas

– address the above, designed to be flexible & optimizable

– much more pleasing & efficient to program with call backs

– With default methods, enabled Collections overhaul.

Page 16: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 20

8λ Syntax and Examples

Page 17: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 21

8Target typing

● Lambda expression is basically

– an anonymous method

– with possibly "captured" enclosing state

● At the grammar level, lambdas are expressions (duh!)

– Can occur anywhere an expression can

– Introduces severe complications in parsing.

● Legally however,

– Lambda needs a context that defines a "target type"

– Everywhere else will have to rejected by the compiler.

– Assignment, initialization, casts, method/ctor invocation, lambda expression body, conditional expressions and return statements are contexts that provide target type.

Page 18: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 22

8Target Typing Examples

Page 19: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 23

8Functional Interfaces

● The target type must be a functional interface

● Functional interface

– Declares a single abstract method

– Some methods don't count:● Default & static methods - they are not abstract● May freely redeclare java.lang.Object's methods

– May be tagged with @FunctionalInterface to express intent

● So the lambda object implements the functional interface

● Another way of constructing objects

– apart from the SE7 ways (new, reflection, serialization, clone ...)

Page 20: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 24

8Lambda Syntax examples

– Parameter types● explicit, or● inferred from target functional interface methods

– Body● expression, or● block.

– ()● can be omitted if a singleton parameter

Page 21: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 25

8Lambda Syntax examples

– Parameter types● explicit, or● inferred from target functional interface methods

– Body● expression, or● block.

– ()● can be omitted if a singleton parameter

Trade-off between conciseness of expression

vsclarity of code

-in the hands of the programmer

Page 22: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 26

8Variable capture

● A lambda can refer to enclosing method's locals– Captured state constitutes the "referencing environment"

– Compiler can infer finality

– Captured state is not mutable.

● Properly: capture of "immutable outer local's value"– Mutability of outer locals implies race conditions

– Mutability would necessarily impose serial execution.

– Lambda creation & invocation could be far apart.● may be in different threads, may be after enclosing method return

● This "constraint" actually enables parallelism.

● Enclosing class instance captured only if referred to.

Page 23: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 27

8Method References

● Similar to lambda expressions

– Require a target type that must be a functional interface

– Serve as instances of the functional interface

– Rather than providing a method body,they refer to an existing method

– Several variants offered.

Page 24: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 28

8Lambda code generation

● Not lowered into anonymous classes - i.e not just syntactic sugar

● What does the following print ?

● Lambda object creation under the hood:

– Handled by "Lambda metafactory" API in JRE.

– Compilers generates suitable calls to the metafactory.

– Enables various optimizations.

Page 25: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 29

8Putting it all together

● Here is a nice example from SOTL[*] [*] http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html

Page 26: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 30

8 JDT features in the works

Page 27: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 31

8 JDT features in the works

Page 28: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 32

8 JDT features in the works

Page 29: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 33

8 JDT features in the works

Page 30: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 35

8

@(JSR 308)

Page 31: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 36

8Annotations in more Places

● Java 5: annotate declarations

– ElementType: packages, classes, fields, methods, locals …

● Java 8: annotate types

– ElementType.TYPE_USE

– ElementType.TYPE_PARAMETER

So what?

Page 32: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 37

8Why Care About Types?

● Type = Constraints on values

To detect anomalies

– missing capability

– incompatible assignment

– undeclared capability

● Constraint checking avoids errors

– No Such Method / Field● Basic statically typed OO

– ClassCastException● Generics

– ??ExceptionMy pet example: NullPointerException

Page 33: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 38

8Let the Type System Handle Nullity

● Ideally: Java would force explicit choice

– String definitely a String, never null

– String? either a String or null

– Type system ensures: no dereferencing of null

● Nullity as a language feature?

– Heavy weight, incompatible change

– Language change for each new constraint?

Page 34: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 39

8Pluggable Type System

● Make it easier to add new constraints

– Only one new syntax for all kinds of constraints

● Make it easier to add new type checkers

– Checker Framework (Michael Ernst – U of Washington)

● Examples

– @NonNull

– @Interned equals(== , equals)

– @Immutable value cannot change (Java 5 ?)

– @ReadOnly value cannot change via this reference

– @UI code requires to run on the SWT UI thread

Page 35: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 40

8

@Target(ElementType.TYPE_USE)@interface NonNull8 {}

@NonNull8 String java8();

Can't Java 5 Do All This?

● We've been lying about the method result– but we can't lie about everything, e.g.:

@Target(ElementType.PARAMETER)@interface NonNull5 {}

void java5(@NonNull5 String arg);

arg is qualified to be non-null

@Target(ElementType.TYPE_USE)@interface NonNull8 {}

void java8(@NonNull8 String arg);

String is qualified to be non-null

String is qualified to be non-null

@Target(ElementType.METHOD)@interface NonNull5 {}

@NonNull5 String java5();

java5 is qualified to be non-null

void printFirstDog(@NonNull List<Dog> dogs) {dogs.get(0).bark();

}

NPE?

Page 36: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 41

8

void bad(List<String> unknown, List<@Nullable String> withNulls) {@NonNull List<@NonNull String> l1 = new ArrayList<>();l1.add(null);String first = l1.get(0);if (first == null) return;

l1 = unknown;l1 = withNulls;

String canNull = withNulls.get(0);System.out.println(canNull.toUpperCase());

}

@NonNull List<@Nullable String> l2 = new ArrayList<>(); l2 can contain null elements

l1 cannot contain null elements

Annotated Generics

void good() {@NonNull List<@NonNull String> l1 = new ArrayList<>();l1.add("Hello");for (String elem : l1)

System.out.println(elem.toUpperCase());

@NonNull List<@Nullable String> l2 = new ArrayList<>();l2.add(null);for (String unknown : l2)

if (unknown != null)System.out.println(unknown.toUpperCase());

}

Null type mismatch: required '@NonNull String'but the provided value is null

Null type mismatch: required '@NonNull String'but the provided value is null

Page 37: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 42

8

void bad(List<String> unknown, List<@Nullable String> withNulls) {@NonNull List<@NonNull String> l1 = new ArrayList<>();l1.add(null);String first = l1.get(0);if (first == null) return;

l1 = unknown;l1 = withNulls;

String canNull = withNulls.get(0);System.out.println(canNull.toUpperCase());

}

@NonNull List<@Nullable String> l2 = new ArrayList<>(); l2 can contain null elements

l1 cannot contain null elements

Annotated Generics

void good() {@NonNull List<@NonNull String> l1 = new ArrayList<>();l1.add("Hello");for (String elem : l1)

System.out.println(elem.toUpperCase());

@NonNull List<@Nullable String> l2 = new ArrayList<>();l2.add(null);for (String unknown : l2)

if (unknown != null)System.out.println(unknown.toUpperCase());

}

Null comparison always yields false:The variable first cannot be null at this location

Null comparison always yields false:The variable first cannot be null at this location

Page 38: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 43

8

void bad(List<String> unknown, List<@Nullable String> withNulls) {@NonNull List<@NonNull String> l1 = new ArrayList<>();l1.add(null);String first = l1.get(0);if (first == null) return;

l1 = unknown;l1 = withNulls;

String canNull = withNulls.get(0);System.out.println(canNull.toUpperCase());

}

@NonNull List<@Nullable String> l2 = new ArrayList<>(); l2 can contain null elements

l1 cannot contain null elements

Annotated Generics

void good() {@NonNull List<@NonNull String> l1 = new ArrayList<>();l1.add("Hello");for (String elem : l1)

System.out.println(elem.toUpperCase());

@NonNull List<@Nullable String> l2 = new ArrayList<>();l2.add(null);for (String unknown : l2)

if (unknown != null)System.out.println(unknown.toUpperCase());

}

Null type safety (type annotations): The expression of type 'List<String>' needs unchecked conversion to conform to '@NonNull List<@NonNull String>'

Null type safety (type annotations): The expression of type 'List<String>' needs unchecked conversion to conform to '@NonNull List<@NonNull String>'

Page 39: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 44

8

void bad(List<String> unknown, List<@Nullable String> withNulls) {@NonNull List<@NonNull String> l1 = new ArrayList<>();l1.add(null);String first = l1.get(0);if (first == null) return;

l1 = unknown;l1 = withNulls;

String canNull = withNulls.get(0);System.out.println(canNull.toUpperCase());

}

@NonNull List<@Nullable String> l2 = new ArrayList<>(); l2 can contain null elements

l1 cannot contain null elements

Annotated Generics

void good() {@NonNull List<@NonNull String> l1 = new ArrayList<>();l1.add("Hello");for (String elem : l1)

System.out.println(elem.toUpperCase());

@NonNull List<@Nullable String> l2 = new ArrayList<>();l2.add(null);for (String unknown : l2)

if (unknown != null)System.out.println(unknown.toUpperCase());

}

Null type mismatch (type annotations):required '@NonNull List<@NonNull String>'but this expression has type 'List<@Nullable String>'

Null type mismatch (type annotations):required '@NonNull List<@NonNull String>'but this expression has type 'List<@Nullable String>'

Page 40: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 45

8

void bad(List<String> unknown, List<@Nullable String> withNulls) {@NonNull List<@NonNull String> l1 = new ArrayList<>();l1.add(null);String first = l1.get(0);if (first == null) return;

l1 = unknown;l1 = withNulls;

String canNull = withNulls.get(0);System.out.println(canNull.toUpperCase());

}

@NonNull List<@Nullable String> l2 = new ArrayList<>(); l2 can contain null elements

l1 cannot contain null elements

Annotated Generics

void good() {@NonNull List<@NonNull String> l1 = new ArrayList<>();l1.add("Hello");for (String elem : l1)

System.out.println(elem.toUpperCase());

@NonNull List<@Nullable String> l2 = new ArrayList<>();l2.add(null);for (String unknown : l2)

if (unknown != null)System.out.println(unknown.toUpperCase());

}

Potential null pointer access: The variable canNull may be null at this location

Potential null pointer access: The variable canNull may be null at this location

Page 41: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 47

8Framework Development (1)

● So you want to be smart:

● But will clients like it?

● If thou usest annotations know thy co/contravariance– @Nullable parameter is irreversible

– Design bug in guava's Predicate / Function

public interface ILib<E> {@NonNull E work(@Nullable E e);

}

public class LibImpl implements ILib<String> {

@Overridepublic @Nullable String work(@NonNull String e) { return null; }

}

Page 42: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 48

8Framework Development (2)

class ToString implements Function<@NonNull Object, @Nullable String> {@Overridepublic @Nullable String apply(@NonNull Object o) { return o.toString(); }

}

● Avoid overspecification, make interfaces null-generic:

● Let clients decide

● Putting the pieces together

public interface Function<I,O> {O apply(I in);

}

<@NonNull I, @Nullable O> Collection<O> map1(Collection<I> in, Function<I, O> f) { … }

<@Nullable I, @NonNull O> Collection<O> map2(Collection<I> in, Function<I, O> f) { … }

...List<@NonNull Object> in = new ArrayList<>();Collection<@Nullable String> out = map1(in, new ToString());

No NPE!

Page 43: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 49

8Caveat: Arrays

● Semantics are changing from Java 7 to Java 8

void test (@NonNull String [] stringsOrNulls) {System.out.println(stringsOrNulls[0]);

}

void test (@NonNull String [] stringsOrNulls) {System.out.println(stringsOrNulls[0]);

}

array of nonnull elements the array can still be null ⇒ NPE

void test (String @NonNull [] stringsOrNulls) {System.out.println(stringsOrNulls[0]);

}

nonnull array NPE- safe (but may print “null”)

Page 44: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 50

8 Status: Annotated Type Analysis

● Implemented EA: @NonNull, @Nullable

– Much analysis already performed● known & unknown bugs

– Editor may show more bogus errors● Project > Clean and Problems View

● Planned: @Uninterned

● Proposed: @UiEffect, @Ui …

– by [Colin S. Gordon, Werner Dietl, Michael D. Ernst, and Dan Grossman]

– SWT: bye, bye, “Invalid thread access”

Page 45: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 51

8Status: Type Annotations

● Supported by

– Compiler

– DOM AST

– APT

● Work in progress

– respect during

● Not yet supported by

– Java model

CtrlCtrl CtrlCtrl 1 CtrlAlt T

Page 46: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 52

8TypeBinding Backstage Story

● Type bindings are “interned”

– OK to use ==

● Broken by encoding type annotations in type bindings

● Solution

– Find/replace == comparisons for T <: TypeBinding

– Tweak our compiler to do this

– Plan: publish the tweak, controlled by @Uninterned

aka “Symbol”

Page 47: JDT embraces lambda expressions

Srikanth Sankaran, Stephan Herrmann: Eclipse and Java 8 - EclipseCon Europe 2013 # 53

8

Dramatis personæ

● Jay Arthanareeswaran● Anirban Chakarborty● Manoj Palat● Shankha Banerjee● Manju Mathew● Noopur Gupta● Deepak Azad● Srikanth Sankaran

● Olivier Thomann● Andy Clement● Michael Rennie

● Jesper S. Møller

● Walter Harley

● Stephan Herrmann

● Dani Megert● Markus Keller

● Early Access:

– http://wiki.eclipse.org/JDT_Core/Java8

● We invite you to test - defect reports welcome !