Removendo avisos elenco desmarcada com genéricos

VeeAyeInIn:

Eu só entrou em genéricos com Java, então eu configurar um projeto pouco para mim. Eu queria fazer um vetor / Point, onde você pode especificar o Number(por exemplo Double, Integer, Long, etc).

Eu acabei ficando um objeto de classe decente para ele, no entanto notado alguns problemas quanto aos 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;
    }
}

O último método, que é o método a adição de números, lança um aviso fundido não verificada. Depois que eu fiz alguma pesquisa, descobri que estava se comportando estranhamente, devido aos genéricos, o que eu sou relativamente novo e incapaz de adequadamente solucionar problemas.

Que tal return (T) bd;cria o aviso? TTem que haver uma instância de um Number, por isso deve ser cast-capaz de um BigDecimal, certo?

Então, eu criei o meu método de teste pouco,

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());

Ele funciona muito bem, imprimir 2.0 5.7e 4.2 9.6.

O problema, então, é quando eu uso um método de Double, como Double#isNaN(). Em seguida, ele joga fora o ClassCastException, Exception in thread "main" java.lang.ClassCastException: java.base/java.math.BigDecimal cannot be cast to java.base/java.lang.Double.

Este comum muito parecia com outras questões pessoas tiveram com este, no entanto, apesar de ir sobre os recursos, eu não entendo por que o erro é lançado utilizando os Doublemétodos. O objeto deve ser um Doubleapós o elenco, certo?

Andy Turner:

Para resolver isso, você precisa fornecer alguns meios de adição de Ts.

Por exemplo, um BinaryOperator<T>é algo que leva em dois Ts, e retorna um T. Assim, você pode definir os para adicionar, por exemplo:

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

Agora, você realmente precisa fornecer uma instância desse ao seu Vector ao criá-lo, por exemplo, como um parâmetro de construtor:

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

E agora usar o BiFunction para adicionar os números:

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

I simplificou sua addNumberssempre tomar dois parâmetros, já que você só invocar com dois parâmetros. Para fazê-lo genericamente, você quer necessidade de fornecer um "zero genérica", ou seja, um valor do tipo T que é zero para esse tipo, ou simplesmente para começar a partir do primeiro elemento na matriz varargs.

Acho que você gosta

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