15 Nisan 2019 Pazartesi

Java 8 Lambda

Giriş
Sözdizimi şöyle
(Parametre,Parametre) -> Body
Lambda için .class Üretilmez
Açıklaması şöyle.
Java has introduced byte code instruction invokedynamic to construct the anonymous class and then  generate byte code for lambdas. So, In case of lambdas java generates the implementation class and generate byte code at runtime.
Lambda için derleme esnasında .class dosyası üretilmez. Üretilmesi için şöyle yaparız.
-Djdk.internal.lambda.dumpProxyClasses=/Your/Path/Here
-> işareti parametreler ve body kısmını ayırır
Açıklaması şöyle.
the -> separates the parameters (left-side) from the actual expression (right side).
Örnek 
Parametre almayan lambda için şöyle yaparız. Parantez boştur.
Runnable r = ()-> System.out.print("Run method");
Örnek
Tek parametre alan lambda için şöyle yaparız. Parametre parantez içine gelir.
Function<String, Integer> parseInt = (String s) -> Integer.parseInt(s);
Integer num= parseInt.apply("10");
Örnek
Arzu edilirse tek parametre parantez içine alınmayabilir. Şöyle yaparız.
Collectors.toMap(entry->entry.getKey(),entry-> {
  ...
});
Lambda Body
Açıklaması şöyle
A lambda body is either a single expression or a block (§14.2). 
Örnek
Eğer body single expression değilse block içine almak gerekir. throw kelimesi single expression olmadığı için şu kod derlenmez.
Supplier<Long> asd = () -> throw new RuntimeException(); // This won't compile :(
Şöyle yaparız.
Supplier<Long> asd = () -> {
    throw new RuntimeException();
};
Lambda ve Checked Exception
Açıklaması şöyle. Checked Excepiton'ları RuntimeException'a çevirerek durum kurtarılabiliyor.
...it is not possible to call a method that throws a checked exception from a lambda directly.
Lambda Anonymous Sınıfa Çevrilir
Açıklaması şöyle.
Well, a lambda expression is just an instance of a special anonymous class that only has one method. Anonymous classes can "capture" variables that are in the surrounding scope.
Örnek
Şöyle yaparız.
import java.lang.reflect.Field;
import java.util.function.Function;

public class Test {
  public static void main(String[] args) {
    final StringBuilder captured = new StringBuilder("foo");
    final String inlined = "bar";
    Function<String, String> lambda = x -> {
      captured.append(x);
      captured.append(inlined);

      return captured.toString();
    };

    for (Field field : lambda.getClass().getDeclaredFields())
      System.out.println(field);
  }
}
Çıktı olarak şunu alırız
private final java.lang.StringBuilder Test$$Lambda$1/424058530.arg$1
Anonymous Sınıf İle Ufak Bir Fark
Açıklaması şöyle. Yani lambda dış sınıfa direkt erişemez.
Lambda expressions are lexically scoped. This means that they do not inherit any names from a supertype or introduce a new level of scoping. Declarations in a lambda expression are interpreted just as they are in the enclosing environment.
Örnek
Normalde anonymous sınıf dış sınıfa erişebilir. Şu kod derlenir.
Thread t1 = new Thread(){
  public void run(){
    try {
      sleep(1000);
    } catch (InterruptedException e) {}
  }
};
Ancak lambda ile derlenmez.
Thread t2 = new Thread(() -> {
  try { 
    sleep(1000);
  } 
  catch (InterruptedException e) {}
});
Lambda Dış Sınıfın Static Üye Alanını Değiştirebilir
Şöyle yaparız. Çıktı olarak true alırız.
public class LambdaNonFinalExample {
  static boolean odd = false;

  public static void main(String[] args) throws Exception {
    runLambda(() -> odd = true);
    System.out.println("Odd=" + odd); //Odd=true
  }

  public static void runLambda(Callable c) throws Exception {
    c.call();
  }

 }
Lambda Yerel Değişkene Erişebilir
Lambda ve Yerel Değişken yazısına taşıdım

Lambda ve Generics
Açıklaması şöyle. Lambda bounded wildcard bilmez.
Lambda argument type is exact, it cannot be ? super or ? extends
Örnek
Elimizde şöyle bir kod olsun.
Predicate<? super String> predicate = s -> s.startsWith("g");
Bu kod aslında şöyledir.
Predicate<String> pred = (Predicate<String>)(s -> s.startsWith("g"));
Predicate<? super String> predicate = pred;


Hiç yorum yok:

Yorum Gönder