en funksjon eller en funksjonsreferanse med et tilhørende "miljø"
definert utenfor selve funksjonen
Condition stopCondition( final Server server ) {
return new Condition() {
public boolean evaluate() {
return server.isRunning();
}
}
}
Java har altså støttet en form for closures lenge (siden 1.1): Funksjoner som refererer til variabler som ikke er en del av parameterlisten (og ikke er globalt).
en funksjon som er definert (og invokert) uten å være bundet til en identifier
Java har tidligere hatt anonyme klasser men ikke anonyme funksjoner - mao ikke lambdaer. Java 8 har altså støtte for både lambdaer og closures, og noen lambdaer vil være closures og noen closures vil være lambdaer.
Runnable r = () -> {};
ActionListener al = (a) -> { log.debug( "Got action: " + a )};
Comparator<String> comp = (String s1, String s2 ) ->
{
out.printf( "Comparing %s to %s %n", s1, s2 );
return s1.length() - s2.length();
};
List<List<Integer>> ll = ...;
ll.stream().reduce(new ArrayList(), (k, v)
-> { k.add( v.stream().reduce(0, (i1, i2)
-> Math.max(i1, i2)) ); return k; } );
Lambda: Argumentlist -> Body
Argumentlist: ( [ [type] name ] * )
Body: Expression | Block
-> Nuff said
Body er ett av følgende:
Tidligere kalt for "Single Abstract Method" / SAM interfaces.
Et interface eller en abstract klasse med nøyaktig EN ikke-implementert metode.
Kompilatoren vil automatisk oversette et lambdauttrykk til en "anonym metode" som implementerer metoden i et slikt interface.
En lambda er altså IKKE implementert vha anonyme klasser
(Demo: javap -c Anon\$1)
Metoder som ikke teller med i antallet ikke-implementerte metoder:
(Demo: Func1)
Initielt skulle også abstrakte klasser kunne være "Functional" og implementeres vha lambda. Dette er droppet pga tekniske vanskeligheter samt muligheten for forvirrende kode:
public abstract class MyFunc {
MyFunc() throws SQLException { sideEffectsHere(); }
public abstract void doit();
}
// Somewhere far away from the declaration of MyFunc:
MyFunc mf = () -> {}; // throws SQLException, and has sideeffects
Tidligere kunne anonyme klasser kun referere til variabler som var final. I java8 har man lempet på dette kravet: Man kan referere til variabler som er effectively final.
Uformell definisjon: En variabel er effectively final dersom det ikke ville blitt en kompileringsfeil dersom man deklarerte den som final.
Det samme gjelder lambdaer: Lambdaer som er closures kan (kun) referere til variabler som er effectively final
(Demo)
For å gjøre kode enda kortere og mer lettlest, har man introdusert metode-referanser. Dette er ikke det mange har savnet:
Method m = MyBusinessClass::myMethod;
Derimot kan dette brukes i lambdaer:
myStringList.stream().map( String::length );
Både statiske metoder og instansemetoder kan refereres. Kompilatoren vil sjekke dette og gi deg
(Demo: Lambda.java)