programacion - que es un atributo en java
¿Referencia de constructor inválida cuando se usa la clase local? (2)
Dado el siguiente código:
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
}
}
mi IDE no me da ningún error Es decir, hasta que intente construir el proyecto y ejecutarlo. Cuando lo hago, me da un error de compilación que se ve así:
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)
Ahora, me imaginé, dado el mensaje de error, que esto no sucedería si foo () fuera estático. Y bastante bien, esto solo sucede si foo () es un método de instancia. Y solo sucede si LocalFoo es una clase local en el método de instancia, y solo si se usa una referencia de constructor (es decir, nunca una referencia de método regular).
Además, si cambio la línea 21 en
ls.stream().map(str -> new LocalFoo(str));
el compilador de repente no da error.
Entonces para recapitular. Si trato de usar una referencia de constructor en una clase local declarada dentro de un método de instancia, el compilador se queja de no poder acceder al constructor, sobre lo cual estoy confundido.
Si alguien pudiera arrojar algo de luz sobre por qué sucede esto, sería apreciado. Gracias.
Parece que LocalFoo
se trata de alguna manera como una clase no estática. Es por eso que afirma que no hay ninguna instancia de prueba dentro del alcance.
Del tutorial:
Las clases locales no son estáticas porque tienen acceso a los miembros de la instancia del bloque adjunto. En consecuencia, no pueden contener la mayoría de los tipos de declaraciones estáticas.
https://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html
El método foo()
o la clase LocalFoo
debe ser estático para que esto funcione. Pero una clase dentro de un método no se puede declarar como estática. Así que tendrías que sacarlo del método si foo()
no fuera estático (como una clase interna, estática). Otra opción es simplemente usar esto:
ls.stream().map(s -> new LocalFoo(s));
Debería haber una forma de decir Test.this.LocalFoo
, pero eso no funciona. Y si lo hizo, el compilador también debería aceptar LocalFoo::new
.
Ahora hay un informe de error: bugs.openjdk.java.net/browse/JDK-8144673
(Ver el comentario de Brian Goetz )
Un problema es que está intentando crear una instancia del Arraylist especificando el tipo genérico en la lista, pero no utilizando el mismo tipo en el Arraylist.
Uso: List ls = new ArrayList ();
También proporcione un constructor predeterminado para LocalFoo