Java - 基本数据类型的动态比较

6

朋友们,

我们正在编写一个验证框架...

我们有一个如下的配置文件...

<root>
<property name="Premium">
    <xmlTag>//Message/Request/Product/Benefit/Premium/amount</xmlTag>
    <valueType>float</valueType>
    <validation condition=">" value="0">Premium Amount cannot be less than Zero.</validation>
</property>

我使用XPath获取XML值,并通过<valueType>元素的值将其转换为浮点数...

不,我也把value="0"转换为浮点数。

现在,我必须应用被指定为condition=">"的条件。

我不想在IF ELSEIF...ELSE循环中执行此操作。

还有其他方法可以将"<"转换为运算符<或在字符串上使用比较运算符吗?

这样,我的代码将更简单,对未来的更多运算符也更有用。

=============================================================================

感谢所有的建议和答案...

我决定使用BeanShell的bsh.Interpreter。它为我完成了工作...

以下是给大家的示例代码...

        System.out.println(new bsh.Interpreter().eval("1 < 0"));
        System.out.println(new bsh.Interpreter().eval("1 > 0"));
        System.out.println(new bsh.Interpreter().eval("1 >= 0"));
        System.out.println(new bsh.Interpreter().eval("0 >= 0"));
        System.out.println(new bsh.Interpreter().eval("1 != 0"));
        System.out.println(new bsh.Interpreter().eval("0 != 0"));
        System.out.println(new bsh.Interpreter().eval("1 == 0"));
        System.out.println(new bsh.Interpreter().eval("0 == 0"));

返回给我 true/false。

谢谢 & 祝好运...


你不必使用 if-then-else 链,可以使用哈希映射。但是动态执行它没有捷径,所以你需要编写大量代码。 - Sergey Kalinichenko
你需要 '<=' 吗?(或者其他多字符运算符) - Angelo Fuchs
1
也请看一下这个问题:https://dev59.com/0HM_5IYBdhLWcg3wThR3,以及这个问题:http://stackoverflow.com/questions/3832323/java-string-and-mathematical-expression-evaluators。 - Angelo Fuchs
是的,我想要涵盖所有可能的比较,如<、<=、>、>=、==、!=等。 - SANSSAN
感谢大家的快速回复和提供的多种可能性...感谢Angelo推荐的不错框架...System.out.println(new bsh.Interpreter().eval("1 < 0")); System.out.println(new bsh.Interpreter().eval("1 > 0")); System.out.println(new bsh.Interpreter().eval("1 >= 0")); System.out.println(new bsh.Interpreter().eval("0 >= 0")); System.out.println(new bsh.Interpreter().eval("1 != 0")); System.out.println(new bsh.Interpreter().eval("0 == 0"));BeanShell 的bsh.Interpreter完成了魔法。 - SANSSAN
3个回答

2

您可以使用switch语句。

char operator = ...;
switch(operator) {
   case '<': return value1 < value2;
   case '=': return value1 == value2;
}

您在上一个case中错误地引入了一个赋值操作; 请使用==代替。 - Costi Ciudatu

2

我建议使用表达式语言,例如Java EL或者更好的Apache Commons Jexl,因为它们更容易集成。以下是从JEXL网站中摘取的代码示例:

    // Assuming we have a JexlEngine instance initialized in our class named 'jexl':
    // Create an expression object for our calculation
    String calculateTax = "((G1 + G2 + G3) * 0.1) + G4";
    Expression e = jexl.createExpression( calculateTax );

    // populate the context
    JexlContext context = new MapContext();
    context.set("G1", businessObject.getTotalSales());
    context.set("G2", taxManager.getTaxCredit(businessObject.getYear()));
    context.set("G3", businessObject.getIntercompanyPayments());
    context.set("G4", -taxManager.getAllowances());
    // ...

    // work it out
    Float result = (Float)e.evaluate(context);

在您的特定示例中,您可以将验证XML更改为以下内容:
<property name="Premium">
    <xmlTag>//Message/Request/Product/Benefit/Premium/amount</xmlTag>
    <valueType>float</valueType>
    <validation expression="Premium> 0">Premium Amount cannot be less than Zero.</validation>
</property>

然后建立自己的JEXL上下文:

JexlContext context = new MapContext();
context.set("PREMIUM", <Premium value fetched from XML>);

在我看来,这是最具可扩展性的解决方案,因为它允许您仅使用一行代码构建复杂的验证表达式。


0

将原始值包装到相应的包装器中:

Float f = new Float(floatValue)

然后您可以使用提供的compareTo()方法进行多态操作。

编辑: 您还可以查看用于表达式解析的全功能实现;除了已经在这里提到的其他实现之外,我还会添加Spring EL


请注意,所有的<、<=、>、>=、==、!=运算符都可以通过compareTo()的结果表来表示,其结果为<0、=0或>=0(例如,<=可以定义为true, true, false,!=可以定义为true, false, true)。 - Russell Zahniser
我无法意识到这如何解决运营商的问题,即每个运算符都有太多的IF-ELSE-ELSEIF跳转。 - Angelo Fuchs
1
抱歉,我觉得我误解了你的问题。你从XML中读取了字符串“<”,想在代码中直接使用它。在Java中这是不可能的。而且,在我看来,即使在提供eval()过程的语言中,你也应该避免这样做。 - Costi Ciudatu
为了完整回答你的问题,你应该保留一个Map,将每个比较“符号”(<<=等)与某个Comparison接口的相应实现关联起来。然后你可以使用comparisons.get("<=").check(a, b)。在check()方法内部,你可以使用Comparable.compareTo或者自己的一些比较器来进行自定义用例。如果你不需要重新编译就能添加新的比较,也可以使用Enum来实现。 - Costi Ciudatu
@给踩票者:难道不应该解释一下为什么要踩票吗?我想从我的错误中学习。 :) - Costi Ciudatu
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接