7,540
edits
Changes
Java-mis
,no edit summary
[[ Java Enum ]]<br>
[[ Java Lamnda ]]
=Java λ=
...
</source>
Ez a '''Consumer<? super T>''' generikus interfész implementációt várja paraméterként, ahol a T a List-ben lévő lista elemek típusa. Valójában a A T listaelemek bármilyen leszármazottját elfogadja. A Láthatjuk az implementációból hogy a forEach metódus az összes listaelemen végigmegy, és minden egyes listaelemre meghívja a Consumer<T> implementáció '''accept()''' metódusát. Az A lista elemeket a saját osztály példányának a példány változójából szedi (vagyis ha van egy ArrayList típusú objektumunk, akkor az maga tárolja a lista elemeket egy belső változójában). A Consumer interfész implementáción múlik, hogy mit fog csinálni az adott listaelemmel. A Consumer implementáció (Consumer<? super T> action) csak egy cső, amibe felülről be tudunk dobni egy T elemet és kidob alul egy R elemet (jelen esetben nincs R elem, mert void típusú a Funkcionális függvény). Tehát az implementációnak nincs állapota. Kap egy inputot és generál belőle egy outputot.
<br><br>
}}
<br><br>
Nézzünk egy lehetséges implementációt:
<source lang="java">
public class MyConstumer implements Consumer<String>{
@Override
public void accept(String t) {
System.out.println(t);
}
}
</source>
A MyConsumer osztály implementálja a Consumer interfész egyetlen metódusát, az accept-et, egy String-et vár inputba és nem ad vissza semmit.
<br><br>
Ennek az implementációs osztálynak ez lenne egy lehetséges felhasználása:
<source lang="java">
public static void main(String[] args) {
List<String> items = new ArrayList<>();
items.add("A");
items.add("B");
items.add("C");
items.add("D");
items.add("E");
Consumer<String> myConsumer = new MyConstumer();
items.forEach(myConsumer);
}
</source>
<source lang="java">
items.forEach(item->System.out.println(item));
</source>
{{note|Az item kívülről nézve nem értelmezhető, szemben egy "normál" függvény hívással, ahol kintről adunk át neki paramétereket. Tehát ez NEM egy külső paraméter. Értelmet csak a forEach belsejében nyer. A lambad kifejezés csak egy állapot nélküli transzformációs függvény, ami inputnak megkapja az '''item'' nevű változót és csinál vele valamit:}}
<br>
<br>
</source>
Ez egy statikus metódus referencia, amivel azt mondjuk meg, hogy a Consumer implementációja a System.out.print(T) metódust fogja meghívni. A lényeg, hogy egy argumentumos legyen a megadott metódus és fel tudjon dolgozni T lista típusú elemet.
<br>
<br>
==Példa 2: saját implementáció==
Az alábbi osztálynak van egy darab osztály változója (variable1) és van egy darab metódusa: processVariable. Ez a metódus egy funkcionális interfészt vár input paraméterként.
<source lang="java">
package hu.otp.auth.loginHelper.util;
import java.util.function.Function;
public class MyLambadClass {
private String variable1;
public MyLambadClass(String a) {
this.variable1 = a;
}
public void processVariable(Function<String, Integer> fn) {
Integer length = fn.apply(variable1);
System.out.println(length.toString());
}
}
</source>
<br>
A processVariable belsejében meghívja a funkcionális interfész '''apply()''' metódusát. (Definiálhattunk volna magunknak saját funkcionális interfész típust, mi most itt egy gyári típust használunk).
<source lang="java">
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Function<T, R> {
R apply(T var1); <<<<<<<<<<<-------------------------------------------------ez itt a lényeg!!!
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (v) -> {
return this.apply(before.apply(v));
};
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (t) -> {
return after.apply(this.apply(t));
};
}
static <T> Function<T, T> identity() {
return (t) -> {
return t;
};
}
}
</source>
Láthatjuk, hogy egy implementálandó metódusa van a "Function" interfésznek, ami T típust vár és R típus ad vissza. Tehát ez egy generikus interfész, és bármi is legyen az implementáció, ott majd meg kell mondani, hogy a pl T=String és R=Intger. De az hogy a Function az egy generikus interfész (generic) annak semmi köze ahhoz hogy ő egy Funkcionális interfész.
<br>
<br>
===Hagyományos implementáció===
A Function interfésznek elkészíthetjük a saját implementációnkat is:
<source lang="java">
class MyFunctionImpl implements Function<String, Integer> {
@Override
public Integer apply(String s) {
return Integer.valueOf(s.length());
}
}
</source>
Az előbb láthattunk, hogy egy metódust kell kötelezően definiálni a Function interfészen, ez az apply. Az implementáció első sorában kikötöttük, hogy T és R String és Integer lesz. Tehát az apply() implementációnknak S-t kell kapnia paraméterként és Integer-t kell visszaadnia. Ez itt teljesül. Nem csinál mást mint a kapott String hosszát visszaadja.
<br>
<br>
Ahhoz hogy ezt használni tudjuk, példányosítani kell, és át kell adni processVariable() metódusnak, ami egy példányosított funkcionális interfészt implementáló osztályt vár. Vagyis egy olyan objektumot, ami egy olyan osztályból készült, ami implementálja a funkcionális interfész metódusát.
<source lang="java"> MyLambadClass myLambadClass =thenComposenew MyLambadClass("adam")==;
MyFunctionImpl myFunction = new MyFunctionImpl();
<source lang="java">
method1().thenCompose(var1 -> method2(var1))
.whenComplete((result, error) -> { ...}
</source>
<source lang="java">
<U> LogCompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> var1);
<br>
<br>
Láthatjuk, hogy egy **'''Function** ''' interfészt vár paraméterül. A 'Function' interfésze nem más mint egy "gyári" funkcionális interfész típus (olyan mint az előző példába a 'Consumer' interfész volt). A funkcionális interfészekkel szemben támasztott követelmény, hogy egy nem implementált metódusuk legyen, ami ebben az esetben az **'''apply()**'''. A **'''T** ''' az input típusa, míg **'''R** ''' a visszatérési típus.
<source lang="java">
<br>
<br>
Tehát a **'''thenCompose(..)** ''' vár egy **'''Function** ''' interfész implementációt és belül meg fogja hívni az **'''apply(..)** ''' metódusát, aminek át fog adni egy T típusú változót, és R típusú változót fog visszavárni visszatérési értékként. Hogy ezt megértsük, nézzük Nézzük meg a **'''thenCompose** ''' implementációját:
<source lang=java>
try {
}
</source>
<source lang="java">
...
.thenCompose(var1 -> method2{ ... //Create a future with string inside new CompletableFuture<String> future = new CompletableFuture<String>(); future.complete("adam"); return future; }) .thenCompose(var1 -> { System.out.println(var1); //will print "adam" ... })
...
</source>
<br>
<br>
===Rövidítés===
Na de mit jelent ez a sor:
<source lang="java">
.thenCompose(var2 -> method3(var2))
</source>
<hr>
<br>
<br>
=Java Method Reference and Constructor Reference=
https://www.amitph.com/java-method-and-constructor-reference/
==Method Reference==
=Mi kell még=Constructor Reference==