java - ''Regla especial de compatibilidad de vacíos'' de Lambda-expresión de declaración
java-8 (3)
El término "expresión de declaración" o "declaración de expresión" se refiere a expresiones que también se pueden utilizar como una declaración. Se describen en la Especificación del lenguaje Java, §14.8. Declaraciones de expresión .
Incluyen:
- Invocaciones de métodos
- Asignaciones
- Expresiones de incremento / decremento
- Expresiones de creación de instancia de clase
Entonces otros ejemplos son:
Consumer<String> b = s -> counter++;
Function<String,Integer> f = s -> counter++;
o
Consumer<String> b = s -> new BigDecimal(s);
Function<String,BigDecimal> f = s -> new BigDecimal(s);
Como regla general, una expresión lambda de la forma
x -> expression
solo es legal para un
Consumer
(o tipo de función
void
en general), si
x -> { expression; }
x -> { expression; }
sería legal también.
Estoy leyendo Java 8 en acción. En la sección 3.5.2 hay un párrafo sobre ''regla de compatibilidad nula'':
Si una lambda tiene una expresión de declaración como cuerpo, es compatible con un descriptor de función que devuelve void (siempre que la lista de parámetros también sea compatible). Por ejemplo, las dos líneas siguientes son legales aunque el método add de una Lista devuelve un valor booleano y no nulo como se esperaba en el contexto del Consumidor (T -> nulo):
// Predicate has a boolean return
Predicate<String> p = s -> list.add(s);
// Consumer has a void return
Consumer<String> b = s -> list.add(s);
¿Cómo describirías ''expresión de declaración'' en general? Pensé que era una declaración o una expresión. Además, esta regla de compatibilidad nula no es 100% clara para mí, ¿puedes pensar en algún otro ejemplo?
Está explicado en la publicación anterior claramente ... ¡Estoy intentando en mi camino!
Se puede proporcionar un descriptor de función con un valor de retorno explícito para un descriptor de función lambda que no devuelve ningún valor.
Por ejemplo, Predicate T -> vs Consumer T -> void lambda expression que toma una entrada y da booleano como retorno, Predicate, puede ser suministrado para Consumer.
En el siguiente ejemplo, public boolean add (E e) {} devuelve boolean, pero puede usarse en lambda para Consumer, que devuelve void.
Predicate<String> p = s -> list.add(s);
p.test("helloworld"); // this returns boolean
Consumer<String> consumerExample = s -> list.add(s);
consumerExample.accept("Welcometokpm"); // this returns void
La estructura común de la expresión lambda es que:
(parameter) -> {body};
{body} con una declaración de retorno de una sola línea es opcional, por ejemplo
Predicate<String> p = s -> list.add(s);
Cuando se utilizan llaves, la declaración de devolución se vuelve obligatoria, por ejemplo
Predicate<String> p = s -> { return list.add(s);};
Ahora, considere una interfaz funcional como Consumer con un método abstracto que no devuelve ningún valor. Puede aceptar una declaración que devuelva cualquier valor porque el compilador ignora la declaración de retorno para dichos métodos abstractos.
Y por lo tanto, las siguientes afirmaciones son verdaderas:
Consumer<String> b = s -> list.add(s);
Equivalente a:
Consumer<String> consumerExample = s -> {list.add(s);};
La siguiente línea es incorrecta:
Consumer<String> consumerExample = s -> {return list.add(s);};
Por lo tanto, si una lambda tiene una expresión de declaración como su cuerpo, es compatible con un descriptor de función que devuelve void (siempre que la lista de parámetros también sea compatible) .