基于字符串动态调用Java函数

时间:2013-08-23 03:01:38

标签: java android dynamic

我正在为Android应用程序构建一个java单元转换器。我正在为用户提供大量不同的单位转换,最终可能会有220次转换,如果您只计算一个方向,则为110次。 I.E.米 - >脚和脚 - >米将是两种不同的转换。

截至目前,我正在计划为每次转换编写小方法,总共220个(我认为这可能是最简单的方法,甚至认为需要一些时间)。现在我的问题是,一旦我设置了2个变量(convertFrom和convertTo),我想知道是否可以动态调用正确的方法?我可以创建if / else if块,但这最终会成为疯狂的代码量,并且希望有更好的方法来调用基于上述2个变量的正确方法。有什么建议吗?

P.S。很抱歉这里没有代码,我只是刚刚开始在这里,我刚刚进入这个阶段的计划阶段。

3 个答案:

答案 0 :(得分:0)

总的来说,你可以这样做:

//invoking a static method (no instance is required)
public Object invoke(final Class<?> clazz, final String name, final Class<?>[] paramTypes, final Object[] args){
    return invoke(null, name, paramTypes, args);
}

//invoking a method on an object (instance is required)
public Object invoke(final Object instance, final Class<?> clazz, final String name, final Class<?>[] paramTypes, final Object[] args) throws Exception{
    assert clazz != null && name != null : "clazz || method == null";
    assert paramTypes.length == args.length : "paramTypes.length != args.length";
    Method method;
    try{
        //to check if the method has been overridden or not
        method = clazz.getDeclaredMethod(name, paramTypes);
    }catch(NoSuchMethodException | SecurityException ex){
        //if method doesn't exist, exception is thrown
        method = clazz.getMethod(name, paramTypes);
    }
    //if method is protected or private
    if(!method.isAccessible())
        method.setAccessible(true);
    return method.invoke(instance, args);
}

如果您尝试调用的方法没有任何参数,请传入一个空的Class<?>[](除了空Object[]之外的参数也是如此)。从此方法返回的对象是刚刚调用的方法的结果。如果方法没有返回类型(void),则返回null。我们的想法是将结果基本上转化为您期望的结果。

答案 1 :(得分:0)

听起来你最好使用带有枚举类型的开关块。

你会创建一个这样的枚举:

public enum Units {
    METERS_TO_FEET("meters", "feet"), FEET_TO_METERS("feet", "meters") /**, etc...*/;

    private final String from;
    private final String to;

    public Units(final String from, final String to) {
        this.from = from;
        this.to = to;
    }

    public static Units fromStrings(String from, String to) {
        if (from != null && to !=null) {
            for (Unit u : Unit.values()) {
                if (from.equalsIgnoreCase(u.from) && to.equalsIgnoreCase(u.to)) {
                    return u;
                }
            }
        }
        return null;
    }
}

并在您的转换方法中使用开关块:`

public int convert(String convertFrom, String convertTo, float fromVal, float toVal) {
    Units u = Units.fromStrings(convertFrom, convertTo);
    if(u == null) {
        throw new IllegalArgumentException("Bad input");
    }
    switch(u) {
    case METERS_TO_FEET :
        /** return meters to feet method on fromVal, toVal */
        break;
    case FEET_TO_METERS :
        /** return feet to meters method on fromVal, toVal */
        break;
    /** etc. */
    }
}

答案 2 :(得分:0)

如何使用将每个单元转换为一个标准测量单位的枚举。然后你可以调用转换将这个标准的测量单位变成你的新单位!

public enum UnitOfMeasure {
    // look at the constructor for the meaning
    // of the parameter
    UNIT1 (1.01),
    UNIT2 (1.02),
    // ...
    UNITX (2.00);

    // conversionFactor will convert each UNIT
    // type to your favorite UnitOfMeasure
    private final double conversionFactor;
    UnitOfMeasure(double conversionFactor) {
        this.conversionFactor = conversionFactor;
    }

    // have a constant for every unit type
    // to choose which unit to convert to
    public static final int UNIT_X = 0;
    public static final int UNIT_Y = 1;
    // ... etc.

    double convert(double value, int convertTo) {
    // a newUnitConversionFactor to convert
    // from our favorite unit of measurement
    // to our desired unit
        double newUnitConversionFactor = -1;
        switch (convertTo) {
        case UNIT_X:
            newUnitConversionFactor = 1.00;
            break;
        case UNIT_Y:
            newUnitConversionFactor = 1.01;
            break;
        // ... etc.
        }
        return value*conversionFactor*newUnitConversionFactor;
    }
}

然后您可以通过选择要转换的单位和要转换为的单位进行转换。例如,如果我想将UNIT1的5.00转换为UNITX,我可以简单地使用它:

UnitOfMeasure.UNIT1.convert(5.00, UnitOfMeasure.UNIT_X);

这样,你也会知道是否会调用转换为你不支持的类型的请求,因为交换机什么都不做,结果是否定的。