首先,我阅读了 Erickson 对“为什么我不能在 Java 接口中定义静态方法?”的有用回复。. 这个问题不是关于“为什么”,而是关于“那么如何?”。
编辑:我原来的例子是不合适的,但我会把它留在下面。
虽然我现在确信,在大多数情况下,我想做的事情是矫枉过正,但在一种情况下可能需要它:
我再举个ParametricFunction
例子。现在让我们看一个复杂的函数,比如Bessel 函数,其中查找表是合适的。这必须被初始化,所以这两个选项是将参数直接传递给构造函数或提供一个init(double[] parameters)
. 后者的缺点是getValue(double x)
必须在每次调用时检查初始化(或者ArrayIndexOutOfBoundsException
必须将其视为初始化检查),因此对于时间要求严格的应用程序,我更喜欢构造函数方法:
interface ParametricFunction {
public double getValue(double x);
}
class BesselFunction implements ParametricFunction {
public BesselFunction(double[] parameters) { ... }
public double getValue(double x) { ... }
}
这就涉及到另一个问题,接口中的构造函数是不可能的。那里有什么好的解决方案?我当然可以使用这种init(double[] parameters)
方法,但我提到了我为什么不这样做的原因。
(编辑:好的,这里有一个实现接口的抽象类)
现在让我们假设ParametricFunction
只允许某些参数,例如正整数。如何检查传递给构造函数的参数的有效性?抛出IllegalArgument
-exception 是可能的,但 acheckParametersValidity(double[] parameters)
似乎更方便。但是需要在构造之前检查参数,所以它必须是静态方法。这就是我真的很想知道一种方法来确保每个实现ParametricFunction
接口的类都定义了这个静态方法。
我知道这个例子是相当人为的,不简单地init
通过接口使用方法的原因是有争议的,我仍然想知道答案。如果您不喜欢它,请将其视为学术问题。
(原始示例)
所以基本上我想要一个接口来提供常用方法和getSimilarObject
方法。对于(编造的)例子
public interface ParametricFunction {
/** @return f(x) using the parameters */
static abstract public double getValue(double x, double[] parameters);
/** @return The function's name */
static abstract public String getName();
/** @return Whether the parameters are valid [added on edit] */
static abstract public boolean checkParameters(double[] parameters);
}
进而
public class Parabola implements ParametricFunction {
/** @return f(x) = parameters[0] * x² + parameters[1] * x + parameters[2] */
static public double getValue(double x, double[] parameters) {
return ( parameters[2] + x*(parameters[1] + x*parameters[0]));
}
static public String getName() { return "Parabola"; }
// edit:
static public boolean checkParameters(double[] parameters) {
return (parameters.length==3);
}
}
由于在当前的 Java 标准中不允许这样做,那么最接近这一点的是什么?
这背后的想法是将几个ParametricFunction
s 放在一个包中并使用反射将它们全部列出,允许用户选择例如要绘制的一个。显然,我们可以提供一个包含可用 s 数组的加载器类ParametricFunction
,但每次实现一个新的时,都必须记住在其中添加它。
编辑:调用它的一个例子是
public double evaluate(String fnName, double x, double parameters) throws (a lot) {
Class<ParametricFunction> c = (Class<ParametricFunction>) ClassLoader.getSystemClassLoader().loadClass(fnName);
Method m = c.getMethod("getValue", x, parameters);
return ((double) m.invoke(null));
}
并打电话evaluate("Parabola", 1, new double[]{1,2,0});
。