Genéricos - inconsistencia compilador [JDK 1.8.0_162]

n247s:

Me encontré con un problema con los genéricos, que me mantiene intrigado de cómo el compilador en realidad se ocupa de los tipos genéricos. Considera lo siguiente:

// simple interface to make it a MCVE
static interface A<F, S> {
    public F getF();    
    public S getS();
}

static <V, S> Comparator<A<V, S>> wrap(Comparator<S> c) {
    return (L, R) -> c.compare(L.getS(), R.getS());
}

Lo siguiente no se compilará debido a que ambos tipos genéricos son reducidos a Objectal llamar thenComparing:

Comparator<A<String, Integer>> c = wrap((L, R) -> Integer.compare(L, R))
    .thenComparing(wrap((L, R) -> Integer.compare(L, R)));

Pero si rompo para arriba como el siguiente ejemplo, compila y se ejecuta () todo correctamente:

Comparator<A<String, Integer>> c = wrap((L, R) -> Integer.compare(L, R));
c = c.thenComparing(wrap((L, R) -> Integer.compare(L, R)));

Entonces la pregunta es: ¿qué pasa aquí? Sospecho que esto se debe a algún extraño comportamiento del compilador en lugar de especificación del lenguaje se pretende? O me estoy perdiendo algo obvio aquí?

Kshdov:

El segundo intento se compila correctamente, porque ha especificado el tipo de una variable a sí mismo, diciendo al compilador de lo que es, porque el compilador no tiene suficiente información para resolverlo.

Mira este ejemplo simplificado, que es de vavr(genial por cierto). Hay una Try<T>clase que representa un resultado de alguna operación. Parámetro genérico Tes el tipo de ese resultado. Hay una fábrica de estática para crear un fracaso inmediato, lo que significa que no tenemos resultado aquí, pero el parámetro genérico sigue ahí:

static <T> Try<T> failure(Throwable exception) {
    return new Try.Failure(exception);
}

De dónde viene el Tvienen de aquí? El uso es el siguiente:

public Try<WeakHashMap> method() {
  return Try.failure(new IllegalArgumentException("Some message"));
}

El Try<WeakHashMap>aquí es mi elección, no los compiladores, en realidad se puede poner lo que quieras allí porque usted está eligiendo el tipo.

Lo mismo en su ejemplo, la Comparatortiene parámetro genérico Stringsolamente, porque ha especificado que el compilador y accedió a ella (como con Try<WeakHashMap>). Al añadir una llamada encadenada que fuerzan el compilador para inferir el tipo en sí, y que era Object, porque lo otro tipo que podría haber sido?

¿Qué más se puede hacer (nótese la Testing.<String, Integer>wrap):

public class Testing {
  static interface A<F, S> {
    public F getF();
    public S getS();
  }

  static <V, S> Comparator<A<V, S>> wrap(Comparator<S> c) {
    return (L, R) -> c.compare(L.getS(), R.getS());
  }

  public static void main(String[] args) {
    Comparator<A<String, Integer>> comp = Testing.<String, Integer>wrap((L, R) -> Integer.compare(L, R))
      .thenComparing(wrap((L, R) -> Integer.compare(L, R)));
  }
}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=173788&siteId=1
Recomendado
Clasificación