Неверная ссылка на конструктор при использовании локального класса?
Учитывая следующий код:
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));
компилятор неожиданно не дает ошибок.
Итак, подведем итоги. Если я пытаюсь использовать ссылку на конструктор в локальном классе, объявленном в методе экземпляра, компилятор жалуется на невозможность доступа к конструктору, из-за чего я запутался.
Если бы кто-то мог пролить свет на то, почему это происходит, это было бы оценено. Благодарю.
2 ответа
Это выглядит как LocalFoo
трактуется как-то как нестатический класс. Вот почему он утверждает, что ни один экземпляр Test не находится в области видимости.
Из учебника:
Локальные классы не являются статичными, потому что они имеют доступ к членам экземпляра вмещающего блока. Следовательно, они не могут содержать большинство видов статических объявлений.
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
(См. Комментарий Брайана Гетца)
Одна проблема заключается в том, что вы пытаетесь создать экземпляр Arraylist, указав общий тип в списке, но не используя тот же тип в Arraylist.
Использование: List ls = new ArrayList();
Также, пожалуйста, предоставьте конструктор по умолчанию для LocalFoo