15 Ağustos 2018 Çarşamba

Method Reference

Giriş
Grameri şöyledir.
MethodReference:
  ExpressionName :: [TypeArguments] Identifier 
  ReferenceType :: [TypeArguments] Identifier 
  Primary :: [TypeArguments] Identifier 
  super :: [TypeArguments] Identifier 
  TypeName . super :: [TypeArguments] Identifier 
  ClassType :: [TypeArguments] new 
  ArrayType :: new
Method Reference FunctionSupplier, BiPredicate ile kullanılabilir.

Kullanım Şekli
4 kullanım şekli var. Bunlar şöyle
Kind                                               Example
========================================================================================
Reference to a static method                      | ContainingClass::staticMethodName
--------------------------------------------------+--------------------------------------
Reference to an instance method of a 
particular object                                 | containingObject::instanceMethodName
--------------------------------------------------+--------------------------------------
Reference to an instance method of an
arbitrary object                                  | ContainingType::methodName
of a particular type                              |
--------------------------------------------------+--------------------------------------
Reference to a constructor                        | ClassName::new
=========================================================================================
new metod
Örnek
Elimizde şöyle bir kod olsun.
private static void test(Callable<Object> call) {

}

private static void test(Runnable run) {

}

static class Gen<T> {

}
Generic kod olduğu için Şöyle yaparız. Derleyiciye yardım olma işine  type witness deniliyor.
test(Gen<String>::new);
static metod
Örnek
static üye metod için şöyle yaparız.
import com.example.MyClass;

someStream.map(MyClass::myStaticMethod)
Örnek
Elimizde şöyle bir kod olsun
interface SomeTest <T>
{
  boolean test(T n, T m);
}

class MyClass
{
  static <T> boolean myGenMeth(T x, T y)
  {
    boolean result = false;
    // ...
    return result;
  }
}
Generic kod olduğu için şöyle yaparız. Derleyiciye yardım olma işine  type witness deniliyor.
SomeTest <Integer> mRef = MyClass :: <Integer> myGenMeth;

Type İçin instance metod
Örnek
Şöyle yaparız.
Predicate<List<String>> p = List::isEmpty;
Object İçin instance metod
Açıklaması şöyle. Instance null olsa bile saklanır.
The timing of method reference expression evaluation is more complex than that of lambda expressions (§15.27.4). When a method reference expression has an expression (rather than a type) preceding the :: separator, that subexpression is evaluated immediately. The result of evaluation is stored until the method of the corresponding functional interface type is invoked; at that point, the result is used as the target reference for the invocation. This means the expression preceding the :: separator is evaluated only when the program encounters the method reference expression, and is not re-evaluated on subsequent invocations on the functional interface type.
Örnek
Elimizde şöyle bir kod olsun.
// Initialize the player map
Map<String, Integer> players = new HashMap<>();
players.put("John", 2);
players.put("Paul", 8);
players.put("Andrew", 5);
Şöyle yaparız.
/ Print all players sorted by rating
players.entrySet().stream()
       .sorted(Map.Entry.comparingByValue())
       .forEach(System.out::println);
Örnek
Şöyle yaparız. Instance null olsa bile kod derlenir ve çalışır.
String s = "Hello World";       
Function<Integer, String> f = s::substring;
s = null;
System.out.println(f.apply(5));
Lambda değişkenin final olmasını istediği için şu kod derlenmez.
String s = "Hello World";
Function<Integer, String> f = i -> s.substring(i); // Doesn't compile!
s = null;
System.out.println(f.apply(5));
Örnek
Şöyle yaparız.
NameCreator creator = new NameCreator();
Function<String, String> func = creator::createName;
Örnek
Şöyle yaparz
Function<String, String> func = this::createName
Diğer

1. Method Reference ve  Lambda Farkı
Method Reference ile şöyle yaparız
JCacheTimeZoneCache::new
Lambda ile şöyle yaparız
() -> new JCacheTimeZoneCache()
Lambda kullanan kod Classloader'ı kullanarak hemen sınıfı yüklemez.

2. Equality
Açıklaması şöyle.
JLS makes no promises about identity or equality of what you get out of method reference expressions.
Örnek
Şöyle yaparız.
Object obj = new Object();

IntSupplier foo = obj::hashCode;
IntSupplier bar = obj::hashCode;

System.out.println(foo == bar);  // false

System.out.println(foo.equals(bar));  // false   
Örnek
Şöyle yaparız.
Object object = ...;
Supplier<String> s1 = object::toString;
Supplier<String> s2 = object::toString;
System.out.println(s1.equals(s2));

Hiç yorum yok:

Yorum Gönder