I just got into generics with Java, so I set up a little project for myself. I wanted to make a Vector / Point where you could specify the Number
(e.g. Double
, Integer
, Long
, etc).
I ended up getting a decent class object for it, however noticed some issues regarding the methods.
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;
}
}
The final method, which is the adding numbers method, throws an unchecked cast warning. After I did some research, I figured out it was behaving oddly due to generics, which I'm relatively new in and unable to properly troubleshoot.
What about return (T) bd;
creates the warning? T
has to be an instance of a Number
, so it should be cast-able to a BigDecimal
, right?
So I created my little testing method,
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());
It works great, printing out 2.0 5.7
and 4.2 9.6
.
The issue then, is when I use a method from Double
, like Double#isNaN()
. It then throws out the ClassCastException, Exception in thread "main" java.lang.ClassCastException: java.base/java.math.BigDecimal cannot be cast to java.base/java.lang.Double
.
This seemed pretty common with other issues people have had with this, however, despite going over the resources, I don't understand why the error is thrown using the Double
methods. The object should be a Double
after the cast, right?