Cómo hacer llamadas lambda interactúan con los interfaces?

Brodiman:

El fragmento de código se muestra a continuación obras. Sin embargo, no estoy seguro de por qué funciona. No estoy siguiendo la lógica de cómo la función lambda está pasando información a la interfaz.

Cuando se pasa el control? ¿Cómo es el compilador haciendo sentido de cada uno nen el bucle y cada uno messagecrea?

Este código se compila y da los resultados esperados. No estoy seguro de cómo acaba.

import java.util.ArrayList;
import java.util.List;

public class TesterClass {

    public static void main(String[] args) {

        List<String> names = new ArrayList<>();

        names.add("Akira");
        names.add("Jacky");
        names.add("Sarah");
        names.add("Wolf");

        names.forEach((n) -> {
            SayHello hello = (message) -> System.out.println("Hello " + message);
            hello.speak(n);
        });
    }

    interface SayHello {
        void speak(String message);
    }
}
Ravindra Ranwala:

El SayHelloes una interfaz abstracta único método que tiene un método que toma una cadena y devuelve vacío. Esto es análogo a un consumidor. Usted se acaba de proporcionar una aplicación de ese método en forma de un consumidor que es similar a la siguiente implementación de la clase interna anónima.

SayHello sh = new SayHello() {
    @Override
    public void speak(String message) {
        System.out.println("Hello " + message);
    }
};

names.forEach(n -> sh.speak(n));

Afortunadamente, su interfaz tiene un método único de tal manera que el sistema de tipos (más formalmente, el algoritmo de resolución de tipo) se puede inferir su tipo que SayHello. Pero si fuera a tener 2 o más métodos, esto no sería posible.

Sin embargo, un enfoque mucho mejor es declarar el consumidor antes de la for-loop y utilizarlo como se muestra a continuación. La declaración de la aplicación para cada iteración crea más objetos que es necesario y parece contra-intuitivo para mí. Esta es la versión mejorada utilizando el método de referencia en lugar de lambda. La referencia al método utilizado aquí acotada llama al método pertinente sobre la helloinstancia declaró anteriormente.

SayHello hello = message -> System.out.println("Hello " + message);
names.forEach(hello::speak);

Actualizar

Teniendo en cuenta que para lambdas sin estado que no capta nada de su ámbito léxico sólo una vez volverá a crearse ejemplo, tanto de los enfoques meramente crear una instancia del SayHello, y no hay alguna ganancia siguiendo el enfoque sugerido. Sin embargo, esto parece ser un detalle de implementación y yo no lo sabía hasta ahora. Así que un enfoque mucho mejor es sólo para pasar de un consumidor a su forEach como se sugiere en el comentario anterior. También tenga en cuenta que todos estos enfoques crea sólo una instancia de la SayHellointerfaz, mientras que el último es más breve. Así es como se ve.

names.forEach(message -> System.out.println("Hello " + message));

Esta respuesta le dará una visión más clara en eso. Aquí está la sección correspondiente de los JLS §15.27.4 : Evaluación en tiempo de ejecución de las expresiones Lambda

Estas reglas están hechas para ofrecer flexibilidad para implementaciones del lenguaje de programación Java, en que:

  • Un nuevo objeto no tiene por qué ser distribuido, de cada evaluación.

De hecho, se pensaba inicialmente cada evaluación crea una nueva instancia, lo que está mal. @Holger gracias por señalarlo, buena captura.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=323455&siteId=1
Recomendado
Clasificación