Java8 - Interfaces, evolved

48
Interfaces, evolved

description

A little talk on Java 8 interfaces I gave a few months back at FastConnect.

Transcript of Java8 - Interfaces, evolved

Page 1: Java8 - Interfaces, evolved

Interfaces, evolved

Page 2: Java8 - Interfaces, evolved

Interfaces, evolved

staticmethods

default methods

traitsfunctionalinterfaces

Page 3: Java8 - Interfaces, evolved

Static Methods

Page 4: Java8 - Interfaces, evolved

Static Methods

//No different from static methods from classes

public interface StaticFoo {

static void foo() {

System.out.println("Static implementation of foo");

}

}

Page 5: Java8 - Interfaces, evolved

Default Methods

Page 6: Java8 - Interfaces, evolved

Default MethodsPreviously, on Java 7

Page 7: Java8 - Interfaces, evolved

Default Methods

signature

class vision…

implem contract…

Java 7 – Interfaces

Page 8: Java8 - Interfaces, evolved

Default Methods

abstract class

utility class

staticmethods

copy / paste

Java 7 – Sharing Implementations

Page 9: Java8 - Interfaces, evolved

Default MethodsNow, in Java 8…

Page 10: Java8 - Interfaces, evolved

Default Methods

public interface Foo {

public default void foo() {

System.out.println("Default implementation of foo()");

}

}

Java 8 – Basic Syntax

Page 11: Java8 - Interfaces, evolved

Default Methods

public interface Itf {

//No implementation; will be overridden

public void foo();

//Default implementation; will be overriden

public default void bar() {

System.out.println("Itf -> bar() [DEFAULT]");

}

//Default implementation; will not be overriden

public default void baz() {

System.out.println("Itf -> baz() [DEFAULT]");

}

}

Java 8 – Call & Overload

Page 12: Java8 - Interfaces, evolved

Default Methods

public class Clazz implements Itf {

@Override

public void foo() {

System.out.println("Clazz -> foo()");

}

@Override

public void bar() {

System.out.println("Clazz -> bar()");

}

}

Java 8 – Call & Overload

Page 13: Java8 - Interfaces, evolved

Default Methods

public class Test {

public static void main(String[] args) {

Clazz clz = new Clazz();

clz.foo();

clz.bar();

clz.baz();

}

}

Java 8 – Call & Overload

Clazz -> foo()Clazz -> bar()Itf -> baz() [DEFAULT]

Page 14: Java8 - Interfaces, evolved

Default MethodsDiamond Inheritance

Page 15: Java8 - Interfaces, evolved

Default Methods

public interface InterfaceA {

public default void foo() {System.out.println("A -> foo()");}

}

public interface InterfaceB {

public default void foo() {System.out.println("B -> foo()");}

}

public class Test implements InterfaceA, InterfaceB {

//Whoops

}

Diamond Inheritance

error: class Test inherits unrelated defaults for foo() from types InterfaceA and InterfaceB

Page 16: Java8 - Interfaces, evolved

Default Methods

//Solution 1 : the class method has the priority

public class Test implements InterfaceA, InterfaceB {

@Override

public void foo() {

System.out.println("Test -> foo()");

}

}

Diamond Inheritance

Page 17: Java8 - Interfaces, evolved

Default Methods

//Solution 2 : we specify which method we want to call

public class Test implements InterfaceA, InterfaceB {

@Override

public void foo() {

InterfaceA.super.foo();

}

}

Diamond Inheritance

Page 18: Java8 - Interfaces, evolved

Default MethodsReflection & Proxies

Page 19: Java8 - Interfaces, evolved

Default Methods

public static void main(String[] args) {

Object proxy = Proxy.newProxyInstance(

Test.class.getClassLoader(),

new Class[]{InterfaceA.class, InterfaceB.class},

(targetProxy, targetMethod, targetMethodArgs) -> {

System.out.println(targetMethod.toGenericString());

return null;

});

((InterfaceA) proxy).foo();

((InterfaceB) proxy).foo();

}

Reflection & Proxies

public default void defaultmethods.InterfaceA.foo()public default void defaultmethods.InterfaceA.foo()

Page 20: Java8 - Interfaces, evolved

Default Methods

public static void main(String[] args) {

Object proxy = Proxy.newProxyInstance(

Test.class.getClassLoader(),

new Class[]{InterfaceA.class, InterfaceB.class},

(targetProxy, targetMethod, targetMethodArgs) -> {

System.out.println(targetMethod.toGenericString());

return null;

});

((InterfaceB) proxy).foo();

((InterfaceA) proxy).foo();

}

Reflection & Proxies

public default void defaultmethods.InterfaceA.foo()public default void defaultmethods.InterfaceA.foo()

Page 21: Java8 - Interfaces, evolved

Default Methods

public static void main(String[] args) {

Object proxy = Proxy.newProxyInstance(

Test.class.getClassLoader(),

new Class[]{InterfaceB.class, InterfaceA.class},

(targetProxy, targetMethod, targetMethodArgs) -> {

System.out.println(targetMethod.toGenericString());

return null;

});

((InterfaceA) proxy).foo();

((InterfaceB) proxy).foo();

}

Reflection & Proxies

public default void defaultmethods.InterfaceB.foo()public default void defaultmethods.InterfaceB.foo()

Page 22: Java8 - Interfaces, evolved

Default Methods

When two or more interfaces of a proxy class contain a method with the same name and parameter signature, the order of the proxy class's interfaces becomes significant. When such a duplicate method is invoked on a proxy instance, the Method object passed to the invocation handler will not necessarily be the one whose declaring class is assignable from the reference type of the interface that the proxy's method was invoked through. This limitation exists because the corresponding method implementation in the generated proxy class cannot determine which interface it was invoked through. Therefore, when a duplicate method is invoked on a proxy instance, the Method object for the method in the foremost interface that contains the method (either directly or inherited through a superinterface) in the proxy class's list of interfaces is passed to the invocation handler's invoke method, regardless of the reference type through which the method invocation occurred.

java.lang.reflect.Proxy, 2014

Reflection & Proxies

Page 23: Java8 - Interfaces, evolved

Traitsfunctional interfaces

VS

Page 24: Java8 - Interfaces, evolved

Traits

Page 25: Java8 - Interfaces, evolved

TraitsFrom what I understood, a trait encapsulates a single behavior.

Page 26: Java8 - Interfaces, evolved

Traits abstract method

derivedmethods

trait

…with their default implementation

Page 27: Java8 - Interfaces, evolved

Traits

public interface Orderable<T> extends Comparable<T> {

//everything relies on the implementation of compareTo

public default boolean isAfter(T other) {

return compareTo(other) > 0;

}

public default boolean isBefore(T other) {

return compareTo(other) < 0;

}

public default boolean isSameAs(T other) {

return compareTo(other) == 0;

}

}

Page 28: Java8 - Interfaces, evolved

Traits

public class Person implements Orderable<Person> {

private final String name;

public Person(String name) {

this.name = name;

}

@Override

public int compareTo(Person other) {

return name.compareTo(other.name);

}

}

Page 29: Java8 - Interfaces, evolved

Traits

public class Test {

public static void main(String[] args) {

Person tony = new Person("Tony Stark");

Person bruce = new Person("Dr. Robert Bruce Banner");

println("Tony compareto Bruce : " + tony.compareTo(bruce));

println("Tony > Bruce : " + tony.isAfter(bruce));

println("Tony < Bruce : " + tony.isBefore(bruce));

println("Tony == Bruce : " + tony.isSameAs(bruce));

}

}

Tony compareTo Bruce : 16Tony > Bruce : trueTony < Bruce : falseTony == Bruce : false

Page 30: Java8 - Interfaces, evolved

FunctionalInterfaces

Page 31: Java8 - Interfaces, evolved

FunctionalInterfacesone abstract / many defaults…

Page 32: Java8 - Interfaces, evolved

FunctionalInterfaces

@FunctionalInterface // optional

public interface Foo {

// 1 and only 1 abstract method

void foo();

// many defaults

default void bar() {…}

default void baz() {…}

}

one abstract / many defaults…

Page 33: Java8 - Interfaces, evolved

FunctionalInterfaces

@FunctionalInterface

public interface Foo {

void foo();

void bar(); // whoops, one too many

}

one abstract / many defaults…

error: Foo is not a functional interface multiple non-overriding abstract methods found in interface Foo1 error

Page 34: Java8 - Interfaces, evolved

FunctionalInterfaces

instance method

constructor

static method

lambda

…to pass them all

Page 35: Java8 - Interfaces, evolved

FunctionalInterfaces

public class Name {

private String firstName;

private String lastName;

public Name(String firstName, String lastName) {

this.firstName = firstName;

this.lastName = lastName;

}

public String getFirstName() { return firstName; }

public String getLastName() { return lastName; }

}

Java 7

Page 36: Java8 - Interfaces, evolved

FunctionalInterfaces

public class NameParser<T> {

public T parse(String name, Creator<T> creator) {

String[] tokens = name.split(" ");

String firstName = tokens[0];

String lastName = tokens[1];

return creator.create(firstName, lastName);

}

}

Java 7

Page 37: Java8 - Interfaces, evolved

FunctionalInterfaces

public interface Creator<T> {

T create(String firstName, String lastName);

}Java 7

Page 38: Java8 - Interfaces, evolved

FunctionalInterfaces

public static void main(String[] args) {

NameParser<Name> parser = new NameParser();

Name res = parser.parse("Bruce Banner", new Creator<Name>() {

@Override

public Name create(String firstName, String lastName) {

return new Name(firstName, lastName);

}

});

}

Java 7

Page 39: Java8 - Interfaces, evolved

FunctionalInterfaces

@FunctionalInterface

public interface Creator<T> {

T create(String firstName, String lastName);

}

Java 8

Page 40: Java8 - Interfaces, evolved

FunctionalInterfaces

Name res = parser.parse("Bruce Banner", Name::new);Java 8

CO

NS

TR

UC

TO

R

Page 41: Java8 - Interfaces, evolved

FunctionalInterfaces

public class Factory {

public static Name createName(String firstName, String lastName) {

return new Name(firstName, lastName);

}

}

Name res = parser.parse("Bruce Banner", Factory::createName);

Java 8

ST

AT

IC M

ET

HO

D

Page 42: Java8 - Interfaces, evolved

FunctionalInterfaces

public class Factory {

public Name createName(String firstName, String lastName) {

return new Name(firstName, lastName);

}

}

Factory factory = new Factory();

Name res = parser.parse("Bruce Banner", factory::createName);

Java 8

INS

TA

NC

E M

ET

HO

D

Page 43: Java8 - Interfaces, evolved

FunctionalInterfaces

Name res = parser.parse("Bruce Banner", (s1, s2) -> new Name(s1, s2));Java 8

LA

MB

DA

EX

PR

ES

SIO

NS

Page 44: Java8 - Interfaces, evolved

FunctionalInterfacesjava.util.function

Page 45: Java8 - Interfaces, evolved

FunctionalInterfacesjava.util.function

Page 46: Java8 - Interfaces, evolved
Page 47: Java8 - Interfaces, evolved

Biblio

Page 48: Java8 - Interfaces, evolved

Biblio

CROISIER, Olivier. Java 8 : du neuf dans les interfaces !, 2014 http://thecodersbreakfast.net/index.php?post/2014/01/20/Java8-du-neuf-dans-les-interfaces

HORSTMANN, Cay S.. Java SE 8 for the Really Impatient. Addison-Wesley, 2014

SEIGNEURIN, Alexis. Java 8 – Interfaces fonctionnelles, 2014 http://blog.ippon.fr/2014/03/18/java-8-interfaces-fonctionnelles/