La eliminación de las advertencias elenco sin marcar con los genéricos

VeeAyeInIn:

Acabo de recibir en los genéricos con Java, por lo que he creado un proyecto pequeño para mí. Yo quería hacer un Vector / punto donde se puede especificar el Number(por ejemplo Double, Integer, Long, etc.).

Que terminó siendo un objeto de clase decente para ella, sin embargo se dio cuenta de algunas cuestiones relacionadas con los métodos.

import java.math.BigDecimal;

@SuppressWarnings("WeakerAccess") // Suppresses weaker access warnings
public class Vector<T extends Number> {

    private T x;
    private T y;

    public Vector() {}

    public Vector(T x, T y) {
        this.x = x;
        this.y = y;
    }

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public T getY() {
        return y;
    }

    public void setY(T y) {
        this.y = y;
    }

    public void dislocate(T offsetX, T offsetY) {
        this.setX(addNumbers(getX(), offsetX));
        this.setY(addNumbers(getY(), offsetY));
    }

    public void dislocate(Vector vector) {
        this.setX(addNumbers(getX(), vector.getX()));
        this.setY(addNumbers(getY(), vector.getY()));
    }

    @SuppressWarnings("unchecked") // Suppresses cast unchecked warnings
    private T addNumbers(Number... numbers) {
        BigDecimal bd = new BigDecimal(0);

        for(Number number : numbers) {
            bd = bd.add(new BigDecimal(number.toString()));
        }

        return (T) bd;
    }
}

El último método, que es el método de añadir números, lanza una advertencia fundido sin marcar. Después de que hice un poco de investigación, me di cuenta de que se estaba comportando de manera extraña, debido a los genéricos, que estoy relativamente nuevo en e incapaz de solucionar problemas adecuadamente.

¿Qué pasa con return (T) bd;crea la advertencia? Ttiene que ser una instancia de una Number, por lo que debe ser capaz de fundición de una BigDecimal, ¿verdad?

Así que creé mi método de prueba,

Vector<Double> vec = new Vector<>(1.0, 3.0);
Vector<Double> vec2 = new Vector<>(2.2, 3.9);
vec.dislocate(1.0, 2.7);
System.out.println(vec.getX() + " " + vec.getY());
vec.dislocate(vec2);
System.out.println(vec.getX() + " " + vec.getY());

Funciona muy bien, imprimir 2.0 5.7y 4.2 9.6.

El problema, entonces, es cuando se utiliza un método de Double, al igual que Double#isNaN(). A continuación, lanza el ClassCastException, Exception in thread "main" java.lang.ClassCastException: java.base/java.math.BigDecimal cannot be cast to java.base/java.lang.Double.

Esto parecía bastante común con otras cuestiones gente ha tenido con esto, sin embargo, a pesar de ir a través de los recursos, que no entiendo por qué el error es lanzado utilizando los Doublemétodos. El objeto debe ser una Doubledespués de la fundición, ¿verdad?

Andy Turner:

Para solucionar esto, es necesario proporcionar algún medio de la adición de Ts.

Por ejemplo, una BinaryOperator<T>es algo que se lleva en dos Ts, y devuelve una T. Por lo tanto, se puede definir aquellos para añadir, por ejemplo:

BinaryOperator<Double> addDoubles = (a, b) -> a+b;
BinaryOperator<BigDecimal> addBigDecimals = (a, b) -> a.add(b);

Ahora, en realidad se necesita suministrar una instancia de este a su vector cuando se crea, por ejemplo, como un parámetro de constructor:

public Vector(BinaryOperator<T> adder) {
  this.adder = adder; // define a field, too.
}

Y ahora utilizar el BiFunction añadir los números:

private T addNumbers(T a, T b) {
  return adder.apply(a, b); // or you could just invoke this directly.
}

Que simplifica su addNumberssiempre tomar dos parámetros, ya que sólo de invocación con dos parámetros. Para hacerlo de forma genérica, más te sea necesario para proporcionar un "cero genérico", es decir, un valor de tipo T, que es cero para ese tipo, o simplemente para iniciar desde el primer elemento de la matriz varargs.

Supongo que te gusta

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