Por lo tanto, tengo un constructor de objetos:
public Func(Function<Var[], Var<T>> function, Var... arguments) {
// Function is a standart 1.8 class
//...
//secret stuff
}
Lo llamo así:
return new Func(new Function<Var[], Var>() {
@Override
public Var apply(Var[] args) {
return instance.getAttribute(args[0].value());
}
}, arguments[0].unpack(instance) // unpack(...) returns Var object
);
Y funciona. Ahora, mi IDE (IntelliJ IDEA) sugiere que yo sustituyo declaración de la función con lambda. Está bien, vamos a hacerlo:
return new Func(
args -> instance.getAttribute(args[0].value()),
arguments[0].unpack(instance)
);
Ahora tengo un error en args
:
tipo de matriz espera; encontrado: 'java.lang.Object'
Así que, al parecer, args
ahora es objeto. ¿Por qué? Es que un error en el IDE o qué?
código completo:
Modelo:
public class Template {
public static void main(String[] args) {
SomeClass someClass = new SomeClass();
System.out.println(someMethod(someClass).value());
}
private static class SomeClass {
Var[] var = new Var[12];
SomeClass() {
var = new Var[12];
for ( int i = 0; i < var.length; i++) {
var[i] = new Var<>(i * 4);
}
}
Var getAttribute(int index) {
return var[index];
}
}
public static Var someMethod(SomeClass instance) {
return new Func(new Function<Var[], Var>() {
@Override
public Var apply(Var[] args) {
return instance.getAttribute((int)args[0].value());
}
}, new Var(4));
}
}
Var.java:
public class Var<T> {
private T value;
public Var(T value) {
this.value = value;
}
public T value() {
return value;
}
}
Func.java:
public class Func<T> extends Var<T> {
private Function<Var[], Var<T>> function;
private Var[] args;
public Func(Function<Var[], Var<T>> function, Var... args) {
super(null);
this.function = function;
this.args = args;
}
@Override
public T value() {
return function.apply(args).value();
}
}
El mensaje de error appers también en el Eclipse-IDE:
El tipo de la expresión debe ser un tipo de matriz pero resuelto a Objeto
Creo que no es un IDE de errores, ni en IntelliJ ni en Eclipse. El compilador necesita para el procesamiento de una expresión lambda siempre un tipo de objetivo que es una interfaz funcional. En el caso de
args -> instance.getAttribute((int)args[0].value())
el tipo de destino es determinado por el primer argumento de la Func-constructor
Function<Var[], Var<T>> function
Sin embargo, esta interfaz funcional es una interfaz genérica. Java compila genéricos utilizando tipo de borrado que significa la sustitución de los parámetros de tipo genérico por el tipo de objeto. Por lo tanto, la interfaz se compila como
interface Function {
public Object apply(Object args);
}
y esto se aplica como tipo de destino. Así, por args un tipo de objeto en lugar de un Var [] - se espera tipo que da como resultado un mensaje de error.
En caso de una clase anónima esto es diferente, ya que se proporcionan más información para la determinación del tipo de destino.
new Function<Var[], Var>(){...}
contiene explícitamente el tipo en la información. Debido a esto args se espera de Var [] - tipo y no se muestra ningún mensaje de error.
Hay dos posibilidades para solucionar el error:
1) En los args elenco getAttribut-método explícitamente a Var [], es decir, reemplazar
(int)args[0].value()
con
(int)((Var[])args)[0].value()
o 2) No usar un genérico interfaz es decir, cambiar la interfaz de
interface Function {
public Var apply(Var[] args);
}
A continuación, se conserva la información de tipo. Por supuesto, el resto del código tiene que ser adaptado en consecuencia.