Puede evitar un argumento desajuste en Java cuando se utiliza "? Extiende" en la declaración genérica?

user1111929:

Estoy tratando de hacer una función que los procesos ordenados listas de elementos (comparables). Por lo tanto, estoy usando el genérico <T extends List<? extends Comparable>>, que obras, siempre y cuando no se necesita ninguna operación de lista específicos que requieren <? extends Comparable>como entrada. Pero en el siguiente fragmento de código (ejemplo más sencillo: el cálculo de la intersección de dos listas ordenadas) de la línea C.add((Comparable)(A.get(posA)));es rechazado por el compilador, alegando que addel argumento necesidades ? extends Comparable, que Comparableaparentemente no lo es.

public static <T extends List<? extends Comparable>> T intersect (T A, T B) {
    T C = (T) A.getClass().newInstance();
    int posA = 0;
    int posB = 0;
    while(posA<A.size()&&posB<B.size()) {
        if (A.get(posA).compareTo(B.get(posB))>0) posB++;
        else if (A.get(posA).compareTo(B.get(posB))<0) posA++;
        else if (A.get(posA).equals(B.get(posB))) {
            C.add((Comparable)(A.get(posA)));
            posA++; posB++;
        }
    }
    return C;
}

¿Cómo debo decirle al compilador que A.get(posA)es de tipo válida ? extends Comparable? Al parecer, la fundición no funciona, y me gustaría que la rutina para aceptar y listas de elementos de comparación arbitrarias (entero, cadena, objetos personalizados, etc.) volver

davidxxx:

¿No te das cuenta todas las declaraciones de tipo inseguras en su código, que varios elencos inseguras?
Usted tiene realmente muchas de ellas. A menudo significa que el enfoque general no es la correcta.

De hecho las cosas no son tan complicadas si usted aprende cómo funcionan los genéricos en Java.
Eso podría ayudarle a:

Estas son las principales cosas que usted debe considerar de acuerdo a su código real: 1) No usar el tipo cruda como List<? extends Comparable>>. Comparablees una clase genérica.
2) No se puede agregar cualquier cosa menos nullen una lista declarada List<? extends Foo>, que utiliza un comodín acotada superior. El último permite hacer la covariante de lista: aceptar Foo y cualquier subclase pero con la limitación anterior. Por lo que no quiere usar eso.
3) Se puede crear una instancia de un genérico ArrayListsin la necesidad de declarar el tipo de método genérico Tpara el ArrayList. Utilizando Tpara el Comparabletipo va a hacer cosas realmente simple.
4) ¿Quieres evitar la reflexión tanto como sea posible.

Siguiendo estas ideas se podría escribir un código que podría parecerse a:

public static <T extends Comparable<T>> List<T> intersect (List<T> A, List<T> B) {
    List<T> list = new ArrayList<>();       
    int posA = 0;
    int posB = 0;
    while(posA<A.size()&&posB<B.size()) {
        if (A.get(posA).compareTo(B.get(posB))>0) posB++;
        else if (A.get(posA).compareTo(B.get(posB))<0) posA++;
        else if (A.get(posA).equals(B.get(posB))) {
            list.add(A.get(posA));
            posA++; posB++;
        }
    }
    return list;
}

Esa fue mi enfoque original, pero el problema aquí es que no todos los que la intersección de dos listas no ArrayList será un ArrayList aquí.

El tipo de la lista no se conoce en tiempo de compilación si se declara Listpara el parámetro. Por lo que inevitablemente terminar con los moldes inseguras.
Por ejemplo :

@SuppressWarnings("unchecked")
public static <T extends Comparable<T>, L extends List<T>> L intersect(L A, L B)  {

    if (A.getClass() != B.getClass()) {
        throw new IllegalArgumentException("not same type between ...");
    }
    List<T> list = A.getClass()
                    .newInstance(); // uncheck

    int posA = 0;
    int posB = 0;
    while (posA < A.size() && posB < B.size()) {
        if (A.get(posA)
             .compareTo(B.get(posB)) > 0)
            posB++;
        else if (A.get(posA)
                  .compareTo(B.get(posB)) < 0)
            posA++;
        else if (A.get(posA)
                  .equals(B.get(posB))) {
            list.add(A.get(posA));
            posA++;
            posB++;
        }
    }
    return (L) list; // uncheck
}

Supongo que te gusta

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