Diferencia entre el método de referencia Receptor vinculado y Receptor no vinculado
Estoy intentando utilizar referencias de métodos de Java 8 en mi código. Hay cuatro tipos de referencias de métodos disponibles.
- Referencia del método estático.
- Método de instancia (receptor vinculado).
- Método de instancia (receptor independiente).
- Referencia del constructor.
Con la referencia del método estático y la referencia del constructor no tengo ningún problema, pero el método de instancia (receptor vinculado) y el método de instancia (receptor independiente) realmente me confundieron. En el receptor vinculado , utilizamos una variable de referencia de objeto para llamar a un método como:
objectRef::Instance Method
En el receptor independiente utilizamos el nombre de clase para llamar a un método como:
ClassName::Instance Method.
Tengo la siguiente pregunta:
- ¿Cuál es la necesidad de diferentes tipos de referencias de métodos, por ejemplo, métodos?
- ¿Cuál es la diferencia entre encuadernado y no encuadernado ? las referencias de métodos de receptor
- ¿Dónde deberíamos usar el receptor vinculado y dónde deberíamos usar el receptor no vinculado ?
También encontré la explicación del receptor vinculado y no vinculado en los libros de características del lenguaje Java 8 , pero todavía estaba confundido con el concepto real.
La idea del receptor independiente es que String::length
te refieres a un método de un objeto que se proporcionará como uno de los parámetros de lambda . Por ejemplo, la expresión lambda (String s) -> s.toUpperCase()
se puede reescribir comoString::toUpperCase
.
Pero acotado se refiere a una situación en la que llamas a un método en una lambda a un objeto externo que ya existe . Por ejemplo, la expresión lambda () -> expensiveTransaction.getValue()
se puede reescribir comoexpensiveTransaction::getValue
.
Situaciones para tres formas diferentes de referencia de métodos
(args) -> ClassName.staticMethod(args)
puede serClassName::staticMethod
// Esto es estático (también puedes pensar como unBound)(arg0, rest) -> arg0.instanceMethod(rest)
puede serClassName::instanceMethod
(arg0
es de tipoClassName
) // Esto no está consolidado(args) -> expr.instanceMethod(args)
puede serexpr::instanceMethod
// Esto está vinculado
Respuesta recuperada del libro Java 8 en acción
Básicamente, los receptores independientes le permiten usar métodos de instancia como si fueran métodos estáticos con un primer parámetro del tipo de declaración, por lo que puede usarlos como funciones pasando cualquier instancia que desee. Con un receptor vinculado, la instancia "destino" es efectivamente parte de la función.
Un ejemplo podría aclarar esto:
import java.util.function.*;
public class Test {
private final String name;
public Test(String name) {
this.name = name;
}
public static void main(String[] args) {
Test t1 = new Test("t1");
Test t2 = new Test("t2");
Supplier<String> supplier = t2::method;
Function<Test, String> function = Test::method;
// No need to say which instance to call it on -
// the supplier is bound to t2
System.out.println(supplier.get());
// The function is unbound, so you need to specify
// which instance to call it on
System.out.println(function.apply(t1));
System.out.println(function.apply(t2));
}
public String method() {
return name;
}
}
Cuando desea que el método se ejecute para una instancia específica de alguna clase, utiliza un receptor vinculado.
Por ejemplo :
Stream.of("x","y").forEach(System.out::println);
se ejecutará println
en una instancia específica de PrintStream
- la System.out
instancia. Por lo tanto System.out.println("x")
, y System.out.println("y")
se ejecutará como resultado de pasar esa referencia de método a forEach
.
Por otro lado, si desea que el método se ejecute para una instancia no especificada de una clase, puede utilizar un receptor independiente.
Por ejemplo :
Stream.of("x","y","").filter(String::isEmpty);
se ejecutará isEmpty()
en cada una de las String
instancias de Stream, es decir "x".isEmpty()
, "y".isEmpty()
y "".isEmpty()
.
Capturé esto de una presentación reciente.