我目前正在学习Java中的泛型,来自C ++它有很大的不同。 我想要一个向量加法,在C ++中,它看起来像这样。 (我知道这段代码编写得不好,只是为了一个简单的例子来展示我想要做的事情)
public class Vect0<T extends Number> {
//Attributs
private T[] _vec;
//Constructeur
public Vect0(T[] vec){
System.out.println("Construction du _vec !");
_vec = vec;
}
//Getter
public int get_length() {
return _vec.length;
}
//Methodes
public void print(){
System.out.print("[");
for (int i = 0; i < _vec.length; ++i){
if (i != _vec.length-1) {
System.out.print(_vec[i] + ", ");
}
else {
System.out.print(_vec[i]);
}
}
System.out.println("]");
}
public T index(int i) {
return _vec[i];
}
public void sum(Vect0<T> other) {
if (other.get_length() == this.get_length()) {
for(int i = 0; i < this.get_length(); ++i) {
Double res = (this.index(i).doubleValue() + other.index(i).doubleValue());
System.out.print(res);
T t = (T) res;
_vec[i] = t;
}
}
}
}
我正在尝试用Java做同样的事情,但我无法通过添加两个泛型T并将值(一个T)放在第一个向量中。我这样做:
private
所以它会打印一个双精度,但是然后投射不起作用而且我收到错误:
线程中的异常&#34; main&#34; java.lang.ArrayStoreException: 在Vect0.sum上的java.lang.Double(Vect0.java:37)at Main.main(Main.java:12)
我希望你能帮助我解决这个问题。 非常感谢你。
答案 0 :(得分:1)
看看下面的代码。您的问题的解释在评论中。
public class TestGenerics {
public static void main(String[] args) {
Integer[] ints = new Integer[] { 1 };
Double[] doubles = new Double[] { 1.0 };
// By not telling the compiler which types you're
// expecting it will not be able to deduce if
// the usage of the generic methods are going
// to be ok or not, because the generics notation is
// erased and is not available at runtime.
// The only thing you will receive by doing this
// is a warning telling you that:
// "Vect0 is a raw type.
// References to generic type Vect0<T> should be parameterized"
Vect0 rawVect0 = new Vect0(ints);
Vect0 rawVect1 = new Vect0(doubles);
// This will throw java.lang.ArrayStoreException
// because you're trying, at runtime, to cast
// a Double object to Integer inside your sum method
// The compiler doesn't have a clue about that so it
// will blow at runtime when you try to use it.
// If you're only working with Integers, than you should not
// cast the result to double and should always work with intValues
rawVect0.sum(rawVect1);
// In Java, when using generics, you should be
// explict about your types using the diamond operator
Vect0<Integer> vect2 = new Vect0<>(ints);
Vect0<Double> vect3 = new Vect0<>(doubles);
// Now that you told the compiler what your types are
// you will receive a compile time error:
// "The method sum(Vect0<Integer>) in the type Vect0<Integer>
// is not applicable for the arguments (Vect0<Double>)"
vect2.sum(vect3);
}
}
如果您阅读了有关ArrayStoreException的内容,它将变得更加清晰:
public class ArrayStoreException extends RuntimeException Thrown to 表示已尝试存储错误类型的 将对象转换为对象数组。例如,以下代码 生成一个ArrayStoreException:
Object x[] = new String[3]; x[0] = new Integer(0);
每当处理Generic方法时,您应该认为Producer应该使用extends,而Consumer应该使用super - PECS 。这是一件好事。看看这个问题: What is PECS (Producer Extends Consumer Super)?
如果您真的希望能够添加不同类型的Number
,那么您的案例的一个解决方案是始终使用一种特定类型(Vect0
)在Double
对象内部工作。看看下面的代码:
public class Vect0<T extends Number> {
// Attributs
private Double[] _vec;
// Constructeur
public Vect0(T[] vec) {
System.out.println("Construction du _vec !");
if (vec instanceof Double[]) {
_vec = (Double[]) Arrays.copyOf(vec, vec.length);
} else {
_vec = Arrays.stream(vec).map(Number::doubleValue).toArray(Double[]::new);
}
}
// Getter
public int get_length() {
return _vec.length;
}
// Methodes
public void print() {
System.out.print("[");
for (int i = 0; i < _vec.length; ++i) {
if (i != _vec.length - 1) {
System.out.print(_vec[i] + ", ");
} else {
System.out.print(_vec[i]);
}
}
System.out.println("]");
}
public Double index(int i) {
return _vec[i];
}
public void sum(Vect0<T> other) {
if (other.get_length() == this.get_length()) {
for (int i = 0; i < this.get_length(); ++i) {
// Now you're only working with Doubles despite of the other object's true type
_vec[i] = index(i) + other.index(i);
}
}
}
}
为了使用它,你应该使用超类Number
引用对象,如下所示:
Vect0<Number> vect2 = new Vect0<>(ints1);
Vect0<Number> vect3 = new Vect0<>(doubles1);
// now it will be able to add two different types without complaining
vect2.sum(vect3);
如果您想要更精细的内容,可以先查看以下问题:How to add two java.lang.Numbers?
干杯!
参考文献: