[Nuevas características de Java 8] 01 Interfaz funcional y expresión Lambda, ¿realmente la conoce?

Java8 fue lanzado por Oracle en 2014 y es la versión más revolucionaria después de Java5.

Java 8 absorbe la esencia de otros lenguajes y trae una serie de nuevas características como programación funcional, expresiones lambda y flujos. Después de aprender estas nuevas características, puede lograr una codificación eficiente y una codificación elegante.

1. Prueba de expresión lambda

La expresión lambada puede entenderse como: una expresión concisa de funciones anónimas pasables. Las expresiones lambda no tienen nombre, tienen listas de parámetros, cuerpos de funciones, tipos de retorno, etc. al igual que los métodos ordinarios;

Echemos un vistazo breve a un ejemplo. El nuevo hilo imprime una cadena y la expresión lambda es muy simple:

new Thread(() -> System.out.println("hello java8 lambda")).start()

La clase Thread acepta una instancia del tipo Runnable. Mirando el código fuente de Jdk, se encuentra que la interfaz Runnable es una interfaz funcional y puede ser reemplazada directamente por una expresión lambda.

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

La sintaxis de las expresiones lambda es muy simple:

() -> System.out.println("hello java8 lambda")
  • () Dentro de los corchetes está la lista de parámetros, si solo hay un parámetro, se puede escribir como: a -> System.out.println (a)
  • -> La flecha es una redacción fija;
  • System.out.println ("hello java8 lambda") es el cuerpo principal de la función. Si hay varias declaraciones, deben incluirse entre llaves, como las siguientes:
(a, b) -> {int sum = a + b; return sum;}

En resumen, el módulo de expresión Lambda se puede curar como:

(parameter) -> {expression} 或者 (parameter) -> {statements; statements; }

Solo un parámetro puede omitir paréntesis

Si no usa expresiones Lambda y usa clases internas anónimas, la escritura no es tan elegante.

// before Java8
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("hello java8 without lambda");
    }
}).start();

 

2. Uso avanzado de Lambda

(1) Interfaz funcional

Una interfaz funcional es una interfaz que define solo un método abstracto. Tenga en cuenta que los métodos predeterminados (predeterminados) están permitidos en Java 8. Incluso si hay muchos métodos predeterminados, siempre que haya un solo método abstracto, esta interfaz sigue siendo una interfaz funcional.

 

Las interfaces funcionales generalmente tienen una anotación @FunctionalInterface en la clase, como:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

(2) ¿Qué pueden hacer las interfaces funcionales?

Por lo general, las expresiones lambda se utilizan en combinación con interfaces funcionales. Las expresiones lambda proporcionan implementaciones para métodos abstractos de interfaces funcionales en forma en línea, tomando la expresión completa como una instancia de la interfaz funcional. Antes de que no haya expresión lambda, usualmente usamos clases internas anónimas para lograr. Para una comparación detallada, vea el código de ejemplo en la primera sección.

 

(3) Descriptor de función

La firma del método abstracto de la interfaz funcional es básicamente la firma de la expresión lambda.Podemos llamar a esta correspondencia un descriptor de función. El método abstracto de una interfaz funcional se abstrae en un descriptor de función. Este proceso es muy importante. Es muy fácil escribir expresiones lambda después de conocer el descriptor de función. por ejemplo:

La interfaz Runnable tiene un método abstracto void run (), que acepta parámetros vacíos y devuelve void, luego el descriptor de la función se puede deducir como: () -> void

La expresión lambda se puede escribir como () -> System.out.println ("hola java8 lambda")

 

(4) Interfaz funcional de uso común

También se definen interfaces funcionales de uso común en java8, para los tipos básicos de java, IntPredicate, LongPredicate y otros tipos. Para obtener más información, consulte el código fuente de jdk.

Interfaz funcional

Descriptor de función

Predicado <T>

T-> booleano

Consumidor <T>

T-> vacío

Función <T, R>

T-> R

Proveedor <T>

() -> T

UnaryOperator <T>

T -> T

Operador binario <T>

(T, T) -> T

BiPredicate <L, R>

(L, R) -> booleano

BiConsumidor <T, U>

(T, U) -> vacío

BiFunción <T, U, R>

(T, U) -> R

En cuanto a las funciones específicas de las interfaces funcionales de Predicate, Consumer, Function, las presentaré en detalle en un artículo posterior, y aquí solo se requiere una impresión general.

 

(5) Refactorizar expresiones lambda en referencias de métodos

La referencia de método puede verse como un atajo para expresiones lambda, que pueden llamar a métodos característicos y pasarlos como parámetros. También puede pensar en las referencias de métodos como un azúcar sintáctico para las expresiones lambda para hacer que las expresiones lambda sean más breves. Por ejemplo, ordene por edad de los estudiantes:

// before
students.sort((s1, s2) -> s1.getAge.compareTo(s2.getAge()))));

// after 使用方法引用
students.sort(Comparator.comparing(Student::getAge()))));

Hay tres tipos principales de referencias a métodos:

  • Referencias de métodos para métodos estáticos

valueOf es un método estático de la clase String. La referencia del método se escribe como String :: valueOf, correspondiente a la expresión lambda: a -> String.valueOf (a)

  • Referencia de método, por ejemplo, métodos de cualquier tipo.

length es un método de instancia de la clase String, la referencia del método se escribe como String :: length, correspondiente a la expresión lambda: (str) -> str.length ()

  • Referencias de métodos, por ejemplo, métodos de objetos existentes.

El tercer tipo es fácil de confundir con el segundo tipo. Los objetos existentes se refieren a métodos de instancia que llaman a objetos externos (no a objetos de parámetros) en expresiones lambda, como:

String str = "hola java8";

() -> str.length ();

La referencia del método correspondiente se escribe como str :: length, tenga en cuenta que no es String :: length

 

Finalmente, resumimos los tres tipos de referencias de métodos de la siguiente manera:

expresión lambda

Referencia de método

 

(argumentos) -> ClassName.staticMethod (argumentos)

ClassName :: staticMethod

Referencia de método de método estático

(arg0, params) -> arg0.instanceMethod (params)

ClassName :: instanceMethod

Referencia de método de instancia interna

arg0

(params) -> arg0.instanceMethod (params)

arg0.instanceMethod

Referencia de método de instancia externa

--- final ---

Los arquitectos de la risa no son tan malos en tecnología. Escanee el código QR o busque "Arquitectos que ríen" en WeChat y siga la cuenta oficial, ¡y se publicarán productos secos más técnicos lo antes posible!

Finalmente, te daré un bono. El risible arquitecto ha recopilado muchos libros electrónicos genuinos sobre tecnologías relacionadas. Después de prestar atención a la cuenta oficial, responde al número 888 para obtenerlo gratis.

Supongo que te gusta

Origin blog.csdn.net/guoguo527/article/details/108805359
Recomendado
Clasificación