Почему на нестатический метод нельзя ссылаться ТОЛЬКО иногда? - PullRequest
0 голосов
/ 16 октября 2018

Я столкнулся с довольно странным поведением компилятора: на нестатический метод можно ссылаться из статического контекста, но не всегда.Насколько я понимаю,

void method() {}

и

void static method(ThisClassName c) {}

должны иметь одинаковую подпись внутри JVM, и, следовательно, их ссылки должны вести себя одинаково, но, очевидно, я ошибаюсь.

Вот мой пример:

Родитель:

package com.example;

abstract class Parent<S> {
    abstract void doSomething(final S s);
}

Дочерний элемент:

package com.example;

import java.util.function.BiConsumer;

class Child extends Parent<String> {
    // This line compiles OK
    private static BiConsumer<Child, String> consumer1 = Child::doSomething;
    // Compiler error: "Non-static method cannot be referenced from a static context."
    private static BiConsumer<Parent, String> consumer2 = Child::doSomething;
    // This line compiles OK
    private static BiConsumer<Parent, String> consumer3 = Child::doSomethingElse;

    @Override
    void doSomething(final String s) {
        // do something
    }

    static void doSomethingElse(final Parent<String> c, final String s) {
        // do something else
    }

}

Проблема в том, что customer2 не может быть установлен из-за ошибки компилятора.

Как я натолкнулся на это: мне нужно было обойти

Map<String, BiConsumer<Parent, ?>>

, и сама карта была построена только один раз (при запуске), поэтому имел смысл сделать ее статической финальной.

1 Ответ

0 голосов
/ 16 октября 2018

Это похоже на случай плохого сообщения об ошибках компилятора.Используя мой компилятор (Eclipse), я вместо этого получаю ошибку:

Тип Child не определяет doSomething (Parent, String), который применим здесь

И действительно, он делаетнет, поскольку метод экземпляра имеет неявный аргумент получателя (this), который для Child::doSomething имеет тип Child, поэтому BiConsumer<Parent, String> не является совместимым целевым типом.

Вы можете использоватьссылка на Parent версию doSomething вместо:

private static BiConsumer<Parent, String> consumer2 = Parent::doSomething;
...