Подтвердить что ты не робот

Недопустимая ссылка на конструктор при использовании локального класса?

С учетом следующего кода:

package com.gmail.oksandum.test;

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {
    }

    public void foo() {
        class LocalFoo {

            LocalFoo(String in) {
                //Some logic
            }

        }

        List<String> ls = new ArrayList<>();
        ls.stream().map(LocalFoo::new); //Line 21
    }

}

моя IDE не дает мне никаких ошибок. То есть, пока я не попытаюсь построить проект и запустить его. Когда я это делаю, это дает мне ошибку компилятора, которая выглядит так:

Error:(21, 24) java: incompatible types: cannot infer type-variable(s) R
    (argument mismatch; invalid constructor reference
      cannot access constructor LocalFoo(java.lang.String)
        an enclosing instance of type com.gmail.oksandum.test.Test is not in scope)

Теперь, я понял, учитывая сообщение об ошибке, что это не произойдет, если foo() были статическими. И совершенно верно, это происходит только в том случае, если foo() является методом экземпляра. И это происходит только в том случае, если LocalFoo является локальным классом в методе экземпляра и только если используется ссылка на конструктор (т.е. Никогда не является регулярной ссылкой на метод).

Что еще, если я сменю строку 21 на

ls.stream().map(str -> new LocalFoo(str));

компилятор не дает ошибок.

Итак, чтобы повторить. Если я попытаюсь использовать ссылку на конструктор в локальном классе, объявленном в методе экземпляра, компилятор жалуется на невозможность доступа к конструктору, о котором я запутался.

Если кто-то может пролить свет на то, почему это происходит, это будет оценено. Спасибо.

4b9b3361

Ответ 1

Похоже, что LocalFoo рассматривается как нестатический класс. Вот почему он утверждает, что ни один экземпляр теста не имеет значения.

Из учебника:

Локальные классы нестатические, поскольку они имеют доступ к членам экземпляра входящего блока. Следовательно, они не могут содержать большинство видов статических объявлений.

https://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html

Метод foo() или класс LocalFoo должен быть статическим, чтобы это работало. Но класс внутри метода не может быть объявлен как статический. Поэтому вам придется переместить его из метода, если foo() должен оставаться нестатическим (как внутренний, статический класс). Другой вариант - просто использовать это:
ls.stream().map(s -> new LocalFoo(s));

Должен быть способ просто сказать Test.this.LocalFoo, но это не работает. И если это сделать, компилятор должен также просто принять LocalFoo::new.

Теперь есть отчет об ошибке: https://bugs.openjdk.java.net/browse/JDK-8144673
(См. комментарий Брайана Гетца)

Ответ 2

Одна из проблем заключается в том, что вы пытаетесь создать экземпляр Arraylist, указав общий тип в списке, но не используя тот же тип в Arraylist.

Использование: Список ls = new ArrayList();

Также укажите конструктор по умолчанию для LocalFoo