如何实例化泛型类型?

时间:2019-08-17 18:47:00

标签: java generics java-8 instance

我正在为Java项目制作一些数学课。我有一个Vector3类,但是我还将需要Vector4和Vector2,但是显然我不想将代码复制粘贴3次。

所以我做的是一个Vector类,它将成为所有vector的母类。我可以只拥有不带任何子类的Vector类,但是我更喜欢拥有这些子类,因为我可以在它们上添加特定的内容,例如Vector3中的欧拉角操作,并且我想将Vector4用作四元数的母类。无论如何,这是我的简化Vector类:

public class Vector {

    public double[] values;

    public Vector(double[] values) {
        this.values = values;
    }

    public int getLength() { 
        return values.length; 
    }

    public static <T extends Vector> T multiply(T vector, double k) {

        double[] values = new double[vector.getLength()];
        for(int i = 0; i < values.length; i++)
            values[i] = k* vector.values[i];
        return new T(values);
    }
}
public class Vector3 extends Vector {
    public Vector3(double[] values) {
        super(values);
    }
}

问题是编译器不允许我实例化T:“类型参数T不能直接实例化”。但是我需要这个T,因为我需要返回的向量与发送的向量具有相同的类型。

如果我执行新的Vector2(4,2).multiply(42),则需要获取Vector2而不是Vector。我还可以在Vector2中制作一个乘法方法,该方法调用Vector乘积,然后将值复制到Vector2中,但是1.太糟糕了; 2。这意味着子矢量之间会有很多复制粘贴; 3。我需要性能,所以那不理想。

我知道我可以使用反射来解决问题,但是这些方法对性能至关重要,因此我必须使其尽可能简单。

我还考虑过更改参数中的向量,因此不必实例化一个新的向量,但这是一个非常糟糕的主意,因为它会导致奇怪的行为。

感谢您的帮助。

2 个答案:

答案 0 :(得分:4)

最简单的方法似乎是在<dxg:GridControl x:Name="Patientgrid" AutoGenerateColumns="AddNew" EnableSmartColumnsGeneration="True" Height="200" ItemsSource="{Binding Data, Source={StaticResource XPCollectionDataSource}}" > <dxg:GridControl.View> <dxg:TableView ShowTotalSummary="True" ShowDataNavigator="True"/> </dxg:GridControl.View> </dxg:GridControl> 类上有一个实例方法:

Vector

然后使用协变量返回类型在每个子类中进行覆盖:

Vector make(double[] values) {
  return new Vector(values);
}

然后您可以在乘法方法中调用它。

class Vector3 extends Vector {
  //...

  @Override Vector3 make(double[] values) {
    return new Vector3(values);
  }

  //...
}

但是说实话,我不会尝试将向量的长度编码为类型。当您需要带有57032个元素的向量时会发生什么?您肯定不想为此创建特定的类,对吗?如果您有两个return vector.make(values); 不同的子类,它们具有相同数量的元素:它们是否兼容(例如,用于加法)?

更自然地处理向量的语言(例如MATLAB)不会将其构建为类型;问问自己您是否真的需要在这里

答案 1 :(得分:3)

如果对性能至关重要,您可能会真正考虑使用乘法方法更改矢量的状态,而不是创建一个新的矢量。我认为,这并不奇怪,只要它是确定性的和有据可查的行为即可。

但是对于不变的向量类,您需要clone向量。

public class Vector implements Cloneable {
    // not a good idea to make it public, if you don't want any changes here
    private double[] values;

    public static <T extends Vector> T multiply(T vector, double k) {
        Vector temp = vector.clone();
        for(int i = 0; i < temp.values.length; i++)
            temp.values[i] = k * temp.values[i];
        // the clone method guarantees that 'temp' is of type T,
        // but since it is not generic, the compiler cannot check it
        @SuppressWarnings("unchecked") 
        T result = (T)temp;
        return result;
    }

    protected Vector clone() {
        try {
            Vector vector = (Vector)super.clone();
            vector.values = Arrays.copyOf(values, values.length);
            return vector;
        } catch (final CloneNotSupportedException exc) {
            // this is a weird design choice of `Object.clone()`, too,
            // but back then, we did not have annotations or anything equivalent
            throw new AssertionError("we forgot to implement java.lang.Cloneable", exc);
        }
    }
}