BiConsumer y el método de referencia de un parámetro

Niko Gambt:

¿Por qué es legal para pasar una referencia de un parámetro de método como un argumento de tipo esperado BiConsumercuyo método abstracto requiere dos argumentos?

Ejemplo:

class Experiment {

    private String name;

    public Experiment(String name) {
        this.name = name;
    }

    public void oneParamMethod(Object o) {
        System.out.println(this.name + " and " + o);
    }

    public <T, S> void executeBiConsumer(BiConsumer<T, S> biCon, T in1, S in2) {
        biCon.accept(in1, in2);
    }

    public static void main(String[] args) {

        // notice that the name is "INSTANCE", but it won't be printed out
        Experiment exp = new Experiment("INSTANCE");

        // executeBiConsumer expects a functional of two params but is given a method 
        // reference of one param. HOW IS THIS LEGAL?
        exp.executeBiConsumer(Experiment::oneParamMethod, new Experiment("PARAM"), 999);
    }
}

Salida:

PARAM and 999

Vamos a cambiar la invocación de tal manera que el segundo argumento es no una instancia de Experimentla siguiente manera:

exp.executeBiConsumer(Experiment::oneParamMethod, new String("INVALID"), 999);

Ahora bien, no se compilará.


  1. ¿Por qué la compilación de código sin quejarse si el segundo argumento es un Experimentejemplo, y por qué no compila lo contrario?
  2. ¿Por qué es válida para pasar una referencia del método de un solo parámetro como argumento que espere BiConsumer?
Eran :

Un método de referencia hace referencia a un argumento un método de instancia que tiene en realidad tiene dos argumentos - el primer argumento es implícita - la instancia en que se ejecuta el método.

Experiment::oneParamMethodes equivalente a (Experiment e, Object o) -> e.oneParamMethod(o).

El BiConsumer<T, S>está de paso a executeBiConsumeres una BiConsumer<Experiment,Object>, lo que significa que debe recibir una instancia de Experimentque el primer argumento del acceptmétodo.

Por lo tanto

exp.executeBiConsumer(Experiment::oneParamMethod, new Experiment("PARAM"), 999);

es válida, pero

exp.executeBiConsumer(Experiment::oneParamMethod, new String("INVALID"), 999);

no es.

Aquí hay una referencia relevante JLS ( 15.13.1 ):

En segundo lugar, dado un tipo de función objetivo con n parámetros, un conjunto de métodos potencialmente aplicables se identifica:

Si la expresión de referencia método tiene la forma ReferenceType :: [TypeArguments] Identificador, los métodos potencialmente aplicables son los métodos miembro del tipo de buscar que tiene un nombre apropiado (dada por Identifier), la accesibilidad, aridad (n o n-1) y el tipo de argumento aridad (derivado de [TypeArguments]), como se especifica en §15.12.2.1.

Dos arities diferentes, n y n-1, se consideran, para tener en cuenta la posibilidad de que esta forma se refiere tanto a un método estático o un método de instancia.

Su tipo de función específica - BiConsumer- tiene 2 parámetros. Por lo tanto los métodos potencialmente aplicables son los métodos miembro del tipo de búsqueda ( Experiment) que tienen el nombre apropiado ( oneParamMethod) y aridad 2 o 1 (es decir, 1 o 2 argumentos). Esto incluye su public void oneParamMethod(Object o)método.

Supongo que te gusta

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