Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

209
Visualizações
¿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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda