slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Type Inference in Java SE 8 PowerPoint Presentation
Download Presentation
Type Inference in Java SE 8

Loading in 2 Seconds...

play fullscreen
1 / 46

Type Inference in Java SE 8 - PowerPoint PPT Presentation


  • 106 Views
  • Uploaded on

Type Inference in Java SE 8. Danie l Smith Java Language Designer. Overview. Context & terminology Target typing Variable dependencies Lambda expressions & method references Migration experience.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Type Inference in Java SE 8' - scott


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
type inference in java se 8
Type Inference in Java SE 8

Daniel SmithJava Language Designer

overview
Overview
  • Context & terminology
  • Target typing
  • Variable dependencies
  • Lambda expressions & method references
  • Migration experience
slide4

The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle.

example
Example

interface Chooser {

int pick(int arg1, int arg2);

<T> T pick(T arg1, T arg2);

}

chooser.pick(23, “hello”).someMethod();

overload resolution
Overload resolution

Which method is i) applicable and ii) best?

int pick(int arg1, int arg2);

<T> T pick(T arg1, T arg2);

chooser.pick(23, “hello”)

Applicable means arguments are compatible with parameter types.

But we don’t know what “T” means…

invocation typing
Invocation typing

What is the generic method’s signature/return for this invocation?

<T> T pick(T arg1, T arg2);

chooser.pick(23, “hello”).someMethod()

In other words, what does “T” mean?

inference variables
Inference variables
  • Inference variables are meta-variables for types. They allow us to talk generally about types. (Compare someMethod on previous slide…)
  • Examples: a, b, s, t, a1, a2
  • Examples in types:
    • t[]
    • List<t>
    • Pair<? extends a1, a2[]>
  • An inference variable (t) is not a type variable (T)
constraint formulas
Constraint formulas
  • Is ArrayList<String> <: List<? extends t> true or false? It depends…
  • Constraint formulas are assertions that constrain the choices for inference variables:
    • ArrayList<String> → List<? extends t>
    • a → int
    • Map<a1, a2> <: Map<String, ?>
  • These assertions come from, e.g., arguments passed to generic parameters (replacing the type variables with inference variables).
bounds
Bounds

Bounds are conclusions drawn from constraint formulas:

  • a = String
  • a <: Number
  • Integer <: a
  • a <: List<b>
  • a <: b
  • false
reduction
Reduction

To get from a constraint formula to bounds, we reduce it:

  • HashMap<String, Number[]> →Map<a1, ? extends a2[]>
  • HashMap<String, Number[]> <: Map<a1, ? extends a2[]>
  • String = a1, Number[] <: a2[]
  • String = a1, Number <: a2
resolution
Resolution
  • Given a set of bounds, choose types for the inference variables that satisfy their bounds.
    • { a = String, b <: Object, Integer <: b }resolves to a=String, b=Integer
    • { Integer <: a, String <: a }resolves to a = Serializable & Comparable<?>
    • { a <: Runnable, a <: Closeable }resolves to a = Runnable & Closeable
  • There is often more than one right answer…
when inference fails
When inference fails

Map<String, List<String>> m = …;

m.put(name, Collections.emptyList());

error: method put in interface Map<K,V> cannot be applied to given types

required: String,List<String>

found: String,List<Object>

m.put(name, Collections.<String>emptyList());

poly expressions
Poly expressions

Poly expressions have different types in different contexts, depending on the target type.

List<String> strings = Collections.emptyList();

List<Integer> ints = Collections.emptyList();

Map<String, Integer> m1 = new HashMap<>();

Map<Integer, String> m2 = new HashMap<>();

contexts for target typing
Contexts for target typing
  • Assignment (including variable declaration, return statement)

List<Float> lf = new ArrayList<>();

  • Lambda expression body

Supplier<List<Float>> lf = () -> new ArrayList<>()

  • Conditional expression (? :)

List<Float> lf = cond ? null : new ArrayList<>();

  • Method argument (including constructors)

float average(List<Float> lf) { … }

average(new ArrayList<>());

delayed resolution
Delayed resolution

List<Number> ln = Arrays.asList(1, 2, 3);

// Java 7: type error

// Java 8: compiles

  • Overload resolution bounds: { Integer <: t }
  • Invocation typing bounds: { Integer <: t, t = Number }
nested invocations
Nested invocations

List<String> ls=Collections.checkedList(new ArrayList<>(), String.class);

  • Overload resolution of constructor:

{ t1 <: Object }

  • checkedList constraints:

ArrayList<_____> → List<t2>

Class<String> → Class<t2>

nested invocations1
Nested invocations

Java 7 Strategy

List<String> ls =Collections.checkedList(new ArrayList<>(), String.class);

  • Overload resolution of constructor:

{ t1 <: Object }

  • ‘checkedList’ constraints:

ArrayList<Object> -> List<t2>

Class<String> -> Class<t2>

nested invocations2
Nested invocations

Java 8 Strategy

List<String> ls =Collections.checkedList(new ArrayList<>(), String.class);

  • Overload resolution of constructor:

{ t1 <: Object }

  • ‘checkedList’ constraints:

ArrayList<t1> -> List<t2>

Class<String> -> Class<t2>

overload resolution target typing
Overload resolution & target typing

Overload resolution is always context-independent.

declared bounds dependencies
Declared bounds & dependencies

interface Widget extends Comparable<Widget> { … }

class Sprog implements Widget { … }

<T extends C, C extends Comparable<C>> void sort(List<T> list);

{ t <: c, c <: Comparable<c> }

List<Sprog> sprogs = …; sort(sprogs);

{ t = Sprog, t <: c, t <: Comparable<c> }

declared bounds dependencies1
Declared bounds & dependencies

Java 7 Strategy

<T extends C, C extends Comparable<C>> void sort(List<T> list);

List<Sprog> sprogs = …; sort(sprogs);

{ t = Sprog, t <: c, c <: Comparable<c> }

Resolution:t = Sprog, c = CAP#1 extends Comparable<CAP#1>

error: invalid inferred types for C; inferred type does not conform to declared bound(s)

inferred: Sprog

bound(s): CAP#1

declared bounds dependencies2
Declared bounds & dependencies

Java 8 Strategy

<T extends C, C extends Comparable<C>> void sort(List<T> list);

List<Sprog> sprogs = …; sort(sprogs);

{ t = Sprog, t <: c, c <: Comparable<c> }

{ t = Sprog, t <: c, Sprog <: c, c <: Comparable<c> }

Sprog <: Comparable<c>

c = Widget

Resolution:t = Sprog, c = Widget

incorporation
Incorporation
  • When adding bounds, identify extra new constraints:
    • a = S and a = Timplies S = T
    • a = Sanda <: Timplies S <: T
    • a = SandT <: aimplies T <: S
    • S <: aanda <: Timplies S <: T
    • a = UandS = Timplies S[a:=U] = T[a:=U]
    • a = UandS <: Timplies S[a:=U] <: T[a:=U]
nesting dependencies
Nesting & dependencies

<C extends Collection<String>> C fill(C coll);

String s = fill(new ArrayList<>()).get(0);

ArrayList<t> -> c

{ ArrayList<t> <: c, c <: Collection<String> }

ArrayList<t> <: Collection<String>

{ t = String, ArrayList<String> <: c, c <: Collection<String> }

lambda expression typing
Lambda expression typing

Implicitly-typed

(x, y) ->x.substring(y)

Explicitly-typed

(String x, int y) ->x.substring(y)

implicitly typed lambda as argument
Implicitly-typed lambda as argument

<T, K extends Comparator<T>> comparing(Function<T,K> getKey);

Comparator<String> byLength = comparing(s -> s.length());

implicitly typed lambda as argument1
Implicitly-typed lambda as argument

<T, K extends Comparator<T>> comparing(Function<T,K> getKey);

<T> comparing(ToIntFunction<T> getKey);

Comparator<String> byLength = comparing(s -> s.length());

// Error: ambiguous overloads

explicitly typed lambda as argument
Explicitly-typed lambda as argument

<T, K extends Comparator<T>> comparing(Function<T,K> getKey);

<T> comparing(ToIntFunction<T> getKey);

Comparator<String> byLength = comparing((String s) -> s.length());

method reference typing
Method reference typing

Inexact

String::substring

Exact

String::getLength

inexact method reference as argument
Inexact method reference as argument

<T, K extends Comparator<T>> comparing(Function<T,K> getKey);

<T> comparing(ToIntFunction<T> getKey);

Comparator<String> byLower = comparing(String::toLowerCase);

// Error: ambiguous overloads

exact method reference as argument
Exact method reference as argument

<T, K extends Comparator<T>> comparing(Function<T,K> getKey);

<T> comparing(ToIntFunction<T> getKey);

Comparator<String> byLength = comparing(String::length);

overloading for lambdas method references
Overloading for lambdas & method references
  • Rule of thumb: don’t declare overloads with functional interface types of the same arity

<T, K extends Comparator<T>> comparing(Function<T,K> getKey);

<T> comparingInt(ToIntFunction<T> getKey);

  • Exception: some other argument can be used to disambiguate
grab bag of other new features
Grab bag of other new features
  • Dependency-based ordering of variable resolution
  • Dependency-based ordering of lambda typing
  • Exception variables prefer resolving to RuntimeException
  • Simulate capture of generic return types
  • More flexibility when unboxing a generic return type
get rid of explicit type arguments
Get rid of explicit type arguments 

Map<String, List<String>> m = …;

m.put(name, Collections.<String>emptyList());

becomes

m.put(name, Collections.emptyList());

(For methods, grep for “.<”; for diamond, look for common generic types)

risk of overload resolution changes
Risk of overload resolution changes 

void m(Object o) { System.out.println(“x”); }

void m(List<Number> ln) { System.out.println(“y”); }

m(Arrays.asList(1, 2, 3));

(Note that it is nearly impossible to improve type checking without tripping over this.)

new freedom
New freedom 
  • Can use diamond everywhere
  • Don’t have to be afraid of ? :
  • Generic methods don’t mind multiple levels of nesting
  • Can define more sophisticated generic APIs
  • No more anonymous inner class boilerplate
slide44
OpenJDK: Lambda Project

JCP: JSR 335

lambda-dev@openjdk.java.net