Rectificación de un tipo de clase con límite superior Iterable y comodín con límite superior Campo de lista Tipo de iterador

Estoy tratando de encontrar el genérico correcto y la disposición comodín para que esto funcione. Se han cambiado los tipos y se ha eliminado el resto del código para mantener esto lo más simple posible.

Aquí tengo una clase genérica con un límite superior de Numberesos implementos Iterable. Contiene uno Listdel tipo genérico.

Quiero pasar una Listde cualquier Numbersubclase y devolver la Iteratorde ese tipo desde el Listcampo.

Aquí está la idea básica que obviamente no funciona.

class GenericQuestion<T extends Number> implements Iterable<T> {
    List<T> numbers;

    GenericQuestion(List<T> number) {
        this.numbers = number;
    }

    public Iterator<T> iterator() {
        return numbers.iterator();
    }

    static void main() {
        for (Number n : new GenericQuestion<Number>(new ArrayList<Integer>())) { // <---- error
            System.out.println(n.byteValue());
        }
    }
}

Esto da el error esperado

incompatible types: ArrayList<Integer> cannot be converted to List<Number>

¡Comodines con límites superiores al rescate! Casi...

class GenericQuestion<T extends Number> implements Iterable<T> {
    List<? extends T> numbers;

    GenericQuestion(List<? extends T> number) {
        this.numbers = number;
    }

    public Iterator<T> iterator() {
        return numbers.iterator(); // <----- error
    }

    static void main() {
        for (Number n : new GenericQuestion<Number>(new ArrayList<Integer>())) {
            System.out.println(n.byteValue());
        }
    }
}

Ahora estoy colgado de los tipos de iteradores en conflicto.

incompatible types: Iterator<CAP#1> cannot be converted to Iterator<T>
  where T is a type-variable:
    T extends Number declared in class GenericQuestion
  where CAP#1 is a fresh type-variable:
    CAP#1 extends T from capture of ? extends T

Ahora, lógicamente, estoy bastante seguro de que sería perfectamente seguro forzar el lanzamiento del iterador devuelto para escribir (Iterator<T>), pero prefiero hacerlo de la manera "correcta". He intentado todo tipo de cosas. Aquí había otro intento desesperado que todavía no funcionaba.

class GenericQuestion<T extends Number> implements Iterable<T> {
    List<T> numbers;

    <U extends Number> GenericQuestion(List<U> number) {
        this.numbers = number; // <----- error
    }

    public Iterator<T> iterator() {
        return numbers.iterator();
    }

    static void main() {
        for (Number n : new GenericQuestion<Number>(new ArrayList<Integer>())) {
            System.out.println(n.byteValue());
        }
    }
}

El error.

incompatible types: List<U> cannot be converted to List<T>
  where U,T are type-variables:
    U extends Number declared in constructor <U>GenericQuestion(List<U>)
    T extends Number declared in class GenericQuestion

Pensé que tal vez una función auxiliar podría cerrar la brecha, pero no tuve suerte con mis intentos.

Esto no parece que deba ser tan difícil. ¿Es el lanzamiento de fuerza realmente el camino a seguir? ¿O hay una declaración genérica que hará que todo esto funcione en conjunto?

Respuesta 1

Creo que debe tener algún tipo de código inseguro en algún lugar si desea una variación T.

Lo que causa esta limitación es Iterable<T>. Se requiere un método Iterator<T> iterator(). No puede estar seguro de que Iterator<? extends T>se puede convertir a Iterator<T>porque el único caso en el que esto es posible es cuando Iterator<? extends T>está Iterator<T>en tiempo de ejecución. Probablemente ya comprenda el hecho de que A<T>no se puede convertir A<U>incluso si T extends U.

Si en su lugar creó su propia MyIterable<T>interfaz, puede hacer esto:

class GenericQuestion<T extends Number> implements MyIterable<T> {
    List<? extends T> numbers;

    GenericQuestion(List<? extends T> number) {
        this.numbers = number;
    }

    public Iterator<? extends T> iterator() {
        return numbers.iterator();
    }

    static void main() {
        GenericQuestion<Number> q = new GenericQuestion<>(new ArrayList<Integer>());
        Iterator<? extends Number> iter = q.iterator();
        System.out.println(iter.next().byteValue());
    }
}

interface MyIterable<T> {
    Iterator<? extends T> iterator();
}

Pero como puede ver, no se puede usar MyIterablecon un bucle for.

Por lo tanto, no lo permite new GenericQuestion<Number>(new ArrayList<Integer>())o escribe un código inseguro.

Respuesta: 2

Un pequeño cambio en su prueba para que no intente forzar GenericQuestion<Number>(sino dejar que inferir tipo):

for (Number n : new GenericQuestion<>(new ArrayList<Integer>())) {

También podría cambiar la declaración para el Listtipo de iterable, como:

class GenericQuestion<T extends Number, L extends List<T>>
        implements Iterable<T> {

    private L numbers;

    GenericQuestion(L number) {
        this.numbers = number;
    }
Respuesta: 3

He estado luchando por encontrar la solución con este error durante 2 semanas. ¿Podría ayudarme con lo que sucedió? Aquí está el seguimiento de la pila de errores: "java.lang.IllegalArgumentException: Nombre para el argumento ...

Soy nuevo en Java y acabo de comenzar a hacer Leetcode - Two Sum. Descubrí que, excepto la solución de fuerza bruta, la solución común es usar Hashmap. Pero todavía no puedo entenderlo. Por ejemplo, esto funciona en mi ...

Estoy tratando de ejecutar un comando: public static void main (String [] args) {int buffer; StringBuilder res = new StringBuilder (); Proceso de proceso; pruebe {proc = Runtime ...

Tengo dos personas que necesito para realizar crossover que son de diferentes longitudes. Los individuos pueden ser así, pero podrían ser mucho más largos: 0 1 2 2 1 2 0 [0] 1 2 1 2 0 1 2 [0] 1 2 1 2 0 2 1 [1] ...