Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

214
Views
¿Cómo sabe Java qué método sobrecargado llamar con expresiones lambda? (Proveedor, Consumidor, Llamable, ...)

En primer lugar, no tengo idea de cómo formular decentemente la pregunta, por lo que se aceptan sugerencias.

Digamos que tenemos los siguientes métodos sobrecargados:

 void execute(Callable<Void> callable) { try { callable.call(); } catch (Exception e) { e.printStackTrace(); } } <T> T execute(Supplier<T> supplier) { return supplier.get(); } void execute(Runnable runnable) { runnable.run(); }

Al salir de esta mesa, obtuve otra pregunta SO

 Supplier () -> x Consumer x -> () BiConsumer x, y -> () Callable () -> x throws ex Runnable () -> () Function x -> y BiFunction x,y -> z Predicate x -> boolean UnaryOperator x1 -> x2 BinaryOperator x1,x2 -> x3

Estos son los resultados que obtengo localmente:

 // Runnable -> expected as this is a plain void execute(() -> System.out.println()); // Callable -> why is it not a Supplier? It does not throw any exceptions.. execute(() -> null); // Supplier -> this returns an Object, but how is that different from returning null? execute(() -> new Object()); // Callable -> because it can throw an exception, right? execute(() -> {throw new Exception();});

¿Cómo sabe el compilador a qué método llamar? ¿Cómo hace, por ejemplo, la distinción entre lo que es un Callable y lo que es un Runnable ?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Todo tiene sentido y tiene un patrón simple además de () -> null es un Callable , creo. El Runnable es claramente diferente del Supplier / Callable ya que no tiene valores de entrada y salida. La diferencia entre Callable y Callable Supplier que manejar las excepciones.

La razón por la que () -> null es un Callable sin excepción es el tipo de retorno de su definición Callable<Void> . Requiere que devuelvas la referencia a algún objeto. La única referencia posible para volver a Void es null . Esto significa que lambda () -> null es exactamente lo que exige su definición. También funcionaría para su ejemplo de Supplier si eliminara la definición de Callable . Sin embargo, utiliza Callable<Void> sobre Supplier<T> ya que Callable tiene el tipo exacto.

Callable se elige sobre Supplier ya que es más específico (como ya se sugirió en un comentario). Los documentos de Java afirman que elige el tipo más específico si es posible:

La inferencia de tipo es la capacidad de un compilador de Java para observar cada invocación de método y la declaración correspondiente para determinar el argumento (o argumentos) de tipo que hacen que la invocación sea aplicable. El algoritmo de inferencia determina los tipos de argumentos y, si está disponible, el tipo que se asigna o se devuelve al resultado. Finalmente, el algoritmo de inferencia intenta encontrar el tipo más específico que funcione con todos los argumentos.

over 4 years ago · Santiago Trujillo Report

0

Creo que he encontrado dónde se describe esto en la documentación oficial, aunque un poco difícil de leer.

Aquí se menciona:

15.27.3. Tipo de una expresión lambda

Tenga en cuenta que, si bien no se permiten las casillas en un contexto de invocación estricto, las expresiones de resultado lambda siempre están permitidas; es decir, la expresión de resultado aparece en un contexto de asignación, independientemente del contexto que encierra la expresión lambda. Sin embargo, si una expresión lambda tipeada explícitamente es un argumento para un método sobrecargado, la verificación más específica prefiere una firma de método que evite encajonar o desencajar el resultado lambda (§15.12.2.5).

y luego aquí (15.12.2.5) se describe analíticamente cómo se elige el método más específico.

Entonces, de acuerdo con esto, por ejemplo, como se describe

Un método aplicable m1 es más específico que otro método aplicable m2, para una invocación con expresiones de argumento e1, ..., ek, si cualquiera de los siguientes es verdadero:

m2 es genérico, y se infiere que m1 es más específico que m2 para las expresiones de argumento e1, ..., ek

Entonces

 // Callable -> why is it not a Supplier? execute(() -> null); <-- Callable shall be picked from 2 options as M2 is generic and M1 is inferred to be more specific void execute(Callable<Void> callable) { // <------ M1 try { callable.call(); } catch (Exception e) { e.printStackTrace(); } } <T> T execute(Supplier<T> supplier) { // <------ M2 is Generic return supplier.get(); }

Por qué se infiere que M1 es más específico se puede rastrear a partir de este proceso descritoaquí (18.5.4 Inferencia de método más específico)

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!