有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何实例化泛型类型?

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

所以我做的是一个向量类,它将是所有向量的母类。我可以只使用没有子类的Vector类,但我更喜欢使用这些子类,因为我可以在它们上添加特定的东西,比如Vector3中的euler角运算,并且我想使用Vector4作为四元数的母类。总之,这里是我的简化向量类:

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,因为我需要返回的向量和发送的向量是相同的类型

如果我做新向量2(4,2)。乘(42),我需要得到一个向量2,而不是一个向量。我还可以在Vector2中创建一个multiply方法,该方法调用向量multiply,然后复制Vector2中的值,但不复制1。太糟糕了,2。这意味着子向量之间需要大量的复制粘贴,3。我需要表现,所以这并不理想

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

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

感谢您的帮助


共 (2) 个答案

  1. # 1 楼答案

    如果它对性能至关重要,您可能会考虑让乘法方法改变向量的状态,而不是创建一个新的向量。在我看来,这并不奇怪,只要它是一种确定性的、有记录的行为

    但是,对于不可变向量类,需要^{}向量

    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);
            }
        }
    }
    
  2. # 2 楼答案

    最简单的方法似乎是在Vector类上有一个实例方法:

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

    然后使用协变返回类型在每个子类中重写:

    class Vector3 extends Vector {
      //...
    
      @Override Vector3 make(double[] values) {
        return new Vector3(values);
      }
    
      //...
    }
    

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

    return vector.make(values);
    

    但老实说,我不会尝试将向量的长度编码到类型中。当您需要一个包含57032个元素的向量时会发生什么?您肯定不想为此创建特定的类,是吗?如果有两个不同的Vector子类具有相同数量的元素,会发生什么情况:它们是否兼容(例如用于添加)

    更自然地处理向量的语言(如MATLAB)不会将其构建到类型中;问问自己,你是否真的需要它