Hay una función eval() en Java?


Tengo una cadena como la siguiente:

String str = "4*5";

Ahora tengo que obtener el resultado de 20 usando la cadena.

Sé que en otros idiomas la función eval() hará esto. ¿Cómo puedo hacer esto en Java?

 123
Author: Francesco Menzani, 2010-04-09

11 answers

Puede utilizar el ScriptEngine clasifique y evalúe como una cadena Javascript.

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
Object result = engine.eval("4*5");

Puede haber una mejor manera, pero esta funciona.

 128
Author: Jeff Storey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-20 13:57:52

No hay ninguna clase o método Java estándar que haga lo que usted quiere. Sus opciones incluyen:

  • Seleccione y utilice alguna biblioteca de evaluación de expresiones de terceros. Por ejemplo JEL o cualquiera de las media docena de bibliotecas listadas aquí.

  • Envuelva la expresión en el código fuente Java para una clase con un método eval, envíela al compilador Java y luego cargue la clase compilada resultante.

  • Use algún lenguaje de scripting que se puede llamar desde Java como evaluador de expresiones. Las posibilidades incluyen Javascript, BeanShell, etc.

  • Escribe tu propio evaluador de expresiones desde cero.

El primer enfoque es probablemente más simple. Los enfoques segundo y tercero son un riesgo potencial de seguridad si obtiene la expresión que se evaluará de un usuario no confiable. (Piense en la inyección de código.)

 42
Author: Stephen C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 04:22:40

Hay muy pocos casos de uso reales en los que sea necesario o deseable poder evaluar un String como un fragmento de código Java. Es decir, preguntar cómo hacer esto es realmente un problema XY : en realidad tienes un problema diferente, que se puede resolver de una manera diferente.

Primero pregúntate, ¿de dónde viene esto String que deseas evaluar? ¿Otra parte de su programa lo generó, o fue una entrada proporcionada por el usuario?

  • Otra parte de mi programa lo generó: por lo tanto, desea que una parte de su programa decida el tipo de operación a realizar, pero no realice la operación, y una segunda parte que realice la operación elegida. En lugar de generar y luego evaluar un String, use la estrategia , Command o Builder patrón de diseño, según corresponda para su caso particular.

  • Es user input : el usuario podría ingresar cualquier cosa, incluyendo comandos que, cuando se ejecuta, podría causar que su programa se porte mal, se bloquee, exponga información que debería ser secreta, dañe la información persistente (como el contenido de una base de datos) y otras cosas desagradables. La única manera de evitar esto sería analizar el String usted mismo, comprobar que no es malicioso, y luego evaluarlo. Pero analizarlo usted mismo es mucho del trabajo que haría la función evalsolicitada, por lo que no se ha ahorrado nada. Peor aún, comprobar que arbitrary Java no era malicioso es imposible , porque comprobar que es el detener el problema.

  • Es una entrada de usuario, pero la sintaxis y semántica del texto permitido para evaluar está muy restringida: Ninguna facilidad de propósito general puede implementar fácilmente un analizador y evaluador de propósito general para cualquier sintaxis y semántica restringida que haya elegido. Lo que necesita hacer es implementar un analizador y evaluador para su sintaxis y semántica elegidas. Si la tarea es simple, usted podría escribir un parser simple recursive-descent o finite-state-machine a mano. Si la tarea es difícil, puede usar un compilador -compiler (como ANTLR) para hacer parte del trabajo por usted.

  • Solo quiero implementar una calculadora de escritorio!: Una tarea, ¿eh? Si pudiera implementar la evaluación de la expresión de entrada utilizando una función eval proporcionada, no sería una tarea de tarea, ¿verdad? Su programa sería tres líneas de largo. Su instructor probablemente espera que escriba el código para un analizador/evaluador aritmético simple. Existe un algoritmo bien conocido, shunting-yard, que puede ser útil.

 29
Author: Raedwald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-14 17:53:45

Podría aconsejarle que use Exp4j. Es fácil de entender como se puede ver en el siguiente código de ejemplo:

Expression e = new ExpressionBuilder("3 * sin(y) - 2 / (x - 2)")
    .variables("x", "y")
    .build()
    .setVariable("x", 2.3)
    .setVariable("y", 3.14);
double result = e.evaluate();
 10
Author: chAlexey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-20 23:16:22

No , no puede tener una "eval" genérica en Java (o cualquier lenguaje compilado). A menos que esté dispuesto a escribir un compilador Java Y una JVM para ser ejecutada dentro de su programa Java.

, puede tener alguna biblioteca para evaluar expresiones algebraicas numéricas como la anterior - vea este hilo para discusión.

 6
Author: DVK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 04:23:38

Como respuestas anteriores, no hay una API estándar en Java para esto.

Puede agregar archivos jar groovy a su ruta y groovy.util.Eval.me ("4*5") hace su trabajo.

 6
Author: Adi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 05:55:56

¡Una forma divertida de resolver tu problema podría ser codificar una función eval() por tu cuenta! ¡Lo he hecho por ti!

Puede usar la biblioteca FunctionSolver simplemente escribiendo FunctionSolver.solveByX(function,valor) dentro de su código. El atributo function es una cadena que representa la función que desea resolver, el atributo value es el valor de la variable independiente de su función (que DEBE ser x).

Si desea resolver un función que contiene más de una variable independiente, puede usar FunctionSolver.función solve (, valores) donde el atributo valueses un HashMap(String,Double) que contiene todos sus atributos independientes (como Strings) y sus respectivos valores (como Doubles).

Otra información: he codificado una versión simple de FunctionSolver , por lo que solo admite Métodos matemáticos que devuelven un doble valor y que acepta uno o dos valores dobles como campos (solo use FunctionSolver.usableMathMethods() si tienes curiosidad) (Estos métodos son: bs, sin, cos, tan, atan2, sqrt, log, log10, pow, exp, min, max, copySign, signum, IEEEremainder, acos, asin, atan, cbrt, ceil, cosh, expm1, floor, hypot, log1p, nextAfter, nextDown, NextUp, random, rint, sinh, tanh, toDegrees, toRadians, ulp). Además, esa biblioteca admite los siguientes operadores: * / + - ^ (incluso si java normalmente no lo hace soporta el operador^).

Una última cosa: al crear esta biblioteca tuve que usar reflections para llamar a Math methods . Creo que es realmente genial, solo echa un vistazo a esto si estás interesado en!

Eso es todo, aquí está el código (y la biblioteca ):

package core;

 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;

 public abstract class FunctionSolver {

public static double solveNumericExpression (String expression) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    return solve(expression, new HashMap<>());
}

public static double solveByX (String function, double value) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    HashMap<String, Double> values = new HashMap<>();
    values.put("x", value);
    return solveComplexFunction(function, function, values);
}

public static double solve (String function, HashMap<String,Double> values) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    return solveComplexFunction(function, function, values);
}

private static double solveComplexFunction (String function, String motherFunction, HashMap<String, Double> values) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    int position = 0;
    while(position < function.length()) {
        if (alphabetic.contains(""+function.charAt(position))) {
            if (position == 0 || !alphabetic.contains(""+function.charAt(position-1))) {
                int endIndex = -1;
                for (int j = position ; j < function.length()-1 ; j++) {
                    if (alphabetic.contains(""+function.charAt(j)) 
                            && !alphabetic.contains(""+function.charAt(j+1))) {
                        endIndex = j;
                        break;
                    }
                }
                if (endIndex == -1 & alphabetic.contains(""+function.charAt(function.length()-1))) {
                    endIndex = function.length()-1;
                }
                if (endIndex != -1) {
                    String alphabeticElement = function.substring(position, endIndex+1);
                    if (Arrays.asList(usableMathMethods()).contains(alphabeticElement)) {
                        //Start analyzing a Math function
                        int closeParenthesisIndex = -1;
                        int openedParenthesisquantity = 0;
                        int commaIndex = -1;
                        for (int j = endIndex+1 ; j < function.length() ; j++) {
                            if (function.substring(j,j+1).equals("(")) {
                                openedParenthesisquantity++;
                            }else if (function.substring(j,j+1).equals(")")) {
                                openedParenthesisquantity--;
                                if (openedParenthesisquantity == 0) {
                                    closeParenthesisIndex = j;
                                    break;
                                }
                            }else if (function.substring(j,j+1).equals(",") & openedParenthesisquantity == 0) {
                                if (commaIndex == -1) {
                                    commaIndex = j;
                                }else{
                                    throw new IllegalArgumentException("The argument of math function (which is "+alphabeticElement+") has too many commas");
                                }
                            }
                        }
                        if (closeParenthesisIndex == -1) {
                            throw new IllegalArgumentException("The argument of a Math function (which is "+alphabeticElement+") hasn't got the closing bracket )");
                        }   
                        String functionArgument = function.substring(endIndex+2,closeParenthesisIndex);
                        if (commaIndex != -1) {
                            double firstParameter = solveComplexFunction(functionArgument.substring(0,commaIndex),motherFunction,values);
                            double secondParameter = solveComplexFunction(functionArgument.substring(commaIndex+1),motherFunction,values);
                            Method mathMethod = Math.class.getDeclaredMethod(alphabeticElement, new Class<?>[] {double.class, double.class});
                            mathMethod.setAccessible(true);
                            String newKey = getNewKey(values);
                            values.put(newKey, (Double) mathMethod.invoke(null, firstParameter, secondParameter));
                            function = function.substring(0, position)+newKey
                                       +((closeParenthesisIndex == function.length()-1)?(""):(function.substring(closeParenthesisIndex+1)));
                        }else {
                            double firstParameter = solveComplexFunction(functionArgument, motherFunction, values);
                            Method mathMethod = Math.class.getDeclaredMethod(alphabeticElement, new Class<?>[] {double.class});
                            mathMethod.setAccessible(true);
                            String newKey = getNewKey(values);
                            values.put(newKey, (Double) mathMethod.invoke(null, firstParameter));
                            function = function.substring(0, position)+newKey
                                       +((closeParenthesisIndex == function.length()-1)?(""):(function.substring(closeParenthesisIndex+1)));
                        }   
                    }else if (!values.containsKey(alphabeticElement)) {
                        throw new IllegalArgumentException("Found a group of letters ("+alphabeticElement+") which is neither a variable nor a Math function: ");
                    }
                }
            }
        }
        position++;
    }
    return solveBracketsFunction(function,motherFunction,values);
}

private static double solveBracketsFunction (String function,String motherFunction,HashMap<String, Double> values) throws IllegalArgumentException{

    function = function.replace(" ", "");
    String openingBrackets = "([{";
    String closingBrackets = ")]}";
    int parenthesisIndex = 0;
    do {
        int position = 0;
        int openParenthesisBlockIndex = -1;
        String currentOpeningBracket = openingBrackets.charAt(parenthesisIndex)+"";
        String currentClosingBracket = closingBrackets.charAt(parenthesisIndex)+"";
        if (contOccouranceIn(currentOpeningBracket,function) != contOccouranceIn(currentClosingBracket,function)) {
            throw new IllegalArgumentException("Error: brackets are misused in the function "+function);
        }
        while (position < function.length()) {
            if (function.substring(position,position+1).equals(currentOpeningBracket)) {
                if (position != 0 && !operators.contains(function.substring(position-1,position))) {
                    throw new IllegalArgumentException("Error in function: there must be an operator following a "+currentClosingBracket+" breacket");
                }
                openParenthesisBlockIndex = position;
            }else if (function.substring(position,position+1).equals(currentClosingBracket)) {
                if (position != function.length()-1 && !operators.contains(function.substring(position+1,position+2))) {
                    throw new IllegalArgumentException("Error in function: there must be an operator before a "+currentClosingBracket+" breacket");
                }
                String newKey = getNewKey(values);
                values.put(newKey, solveBracketsFunction(function.substring(openParenthesisBlockIndex+1,position),motherFunction, values));
                function = function.substring(0,openParenthesisBlockIndex)+newKey
                           +((position == function.length()-1)?(""):(function.substring(position+1)));
                position = -1;
            }
            position++;
        }
        parenthesisIndex++;
    }while (parenthesisIndex < openingBrackets.length());
    return solveBasicFunction(function,motherFunction, values);
}

private static double solveBasicFunction (String function, String motherFunction, HashMap<String, Double> values) throws IllegalArgumentException{

    if (!firstContainsOnlySecond(function, alphanumeric+operators)) {
        throw new IllegalArgumentException("The function "+function+" is not a basic function");
    }
    if (function.contains("**") |
        function.contains("//") |
        function.contains("--") |
        function.contains("+*") |
        function.contains("+/") |
        function.contains("-*") |
        function.contains("-/")) {
        /*
         * ( -+ , +- , *- , *+ , /- , /+ )> Those values are admitted
         */
        throw new IllegalArgumentException("Operators are misused in the function");
    }
    function = function.replace(" ", "");
    int position;
    int operatorIndex = 0;
    String currentOperator;
    do {
        currentOperator = operators.substring(operatorIndex,operatorIndex+1);
        if (currentOperator.equals("*")) {
            currentOperator+="/";
            operatorIndex++;
        }else if (currentOperator.equals("+")) {
            currentOperator+="-";
            operatorIndex++;
        }
        operatorIndex++;
        position = 0;
        while (position < function.length()) {
            if ((position == 0 && !(""+function.charAt(position)).equals("-") && !(""+function.charAt(position)).equals("+") && operators.contains(""+function.charAt(position))) ||
                (position == function.length()-1 && operators.contains(""+function.charAt(position)))){
                throw new IllegalArgumentException("Operators are misused in the function");
            }
            if (currentOperator.contains(function.substring(position, position+1)) & position != 0) {
                int firstTermBeginIndex = position;
                while (firstTermBeginIndex > 0) {
                    if ((alphanumeric.contains(""+function.charAt(firstTermBeginIndex))) & (operators.contains(""+function.charAt(firstTermBeginIndex-1)))){
                        break;
                    }
                    firstTermBeginIndex--;
                }
                if (firstTermBeginIndex != 0 && (function.charAt(firstTermBeginIndex-1) == '-' | function.charAt(firstTermBeginIndex-1) == '+')) {
                    if (firstTermBeginIndex == 1) {
                        firstTermBeginIndex--;
                    }else if (operators.contains(""+(function.charAt(firstTermBeginIndex-2)))){
                        firstTermBeginIndex--;
                    }
                }
                String firstTerm = function.substring(firstTermBeginIndex,position);
                int secondTermLastIndex = position;
                while (secondTermLastIndex < function.length()-1) {
                    if ((alphanumeric.contains(""+function.charAt(secondTermLastIndex))) & (operators.contains(""+function.charAt(secondTermLastIndex+1)))) {
                        break;
                    }
                    secondTermLastIndex++;
                }
                String secondTerm = function.substring(position+1,secondTermLastIndex+1);
                double result;
                switch (function.substring(position,position+1)) {
                    case "*": result = solveSingleValue(firstTerm,values)*solveSingleValue(secondTerm,values); break;
                    case "/": result = solveSingleValue(firstTerm,values)/solveSingleValue(secondTerm,values); break;
                    case "+": result = solveSingleValue(firstTerm,values)+solveSingleValue(secondTerm,values); break;
                    case "-": result = solveSingleValue(firstTerm,values)-solveSingleValue(secondTerm,values); break;
                    case "^": result = Math.pow(solveSingleValue(firstTerm,values),solveSingleValue(secondTerm,values)); break;
                    default: throw new IllegalArgumentException("Unknown operator: "+currentOperator);
                }
                String newAttribute = getNewKey(values);
                values.put(newAttribute, result);
                function = function.substring(0,firstTermBeginIndex)+newAttribute+function.substring(secondTermLastIndex+1,function.length());
                deleteValueIfPossible(firstTerm, values, motherFunction);
                deleteValueIfPossible(secondTerm, values, motherFunction);
                position = -1;
            }
            position++;
        }
    }while (operatorIndex < operators.length());
    return solveSingleValue(function, values);
}

private static double solveSingleValue (String singleValue, HashMap<String, Double> values) throws IllegalArgumentException{

    if (isDouble(singleValue)) {
        return Double.parseDouble(singleValue);
    }else if (firstContainsOnlySecond(singleValue, alphabetic)){
        return getValueFromVariable(singleValue, values);
    }else if (firstContainsOnlySecond(singleValue, alphanumeric+"-+")) {
        String[] composition = splitByLettersAndNumbers(singleValue);
        if (composition.length != 2) {
            throw new IllegalArgumentException("Wrong expression: "+singleValue);
        }else {
            if (composition[0].equals("-")) {
                composition[0] = "-1";
            }else if (composition[1].equals("-")) {
                composition[1] = "-1";
            }else if (composition[0].equals("+")) {
                composition[0] = "+1";
            }else if (composition[1].equals("+")) {
                composition[1] = "+1";
            }
            if (isDouble(composition[0])) {
                return Double.parseDouble(composition[0])*getValueFromVariable(composition[1], values);
            }else if (isDouble(composition[1])){
                return Double.parseDouble(composition[1])*getValueFromVariable(composition[0], values);
            }else {
                throw new IllegalArgumentException("Wrong expression: "+singleValue);
            }
        }
    }else {
        throw new IllegalArgumentException("Wrong expression: "+singleValue);
    }
}

private static double getValueFromVariable (String variable, HashMap<String, Double> values) throws IllegalArgumentException{

    Double val = values.get(variable);
    if (val == null) {
        throw new IllegalArgumentException("Unknown variable: "+variable);
    }else {
        return val;
    }
}

/*
 * FunctionSolver help tools:
 * 
 */

private static final String alphabetic = "abcdefghilmnopqrstuvzwykxy";
private static final String numeric = "0123456789.";
private static final String alphanumeric = alphabetic+numeric;
private static final String operators = "^*/+-"; //--> Operators order in important!

private static boolean firstContainsOnlySecond(String firstString, String secondString) {

    for (int j = 0 ; j < firstString.length() ; j++) {
        if (!secondString.contains(firstString.substring(j, j+1))) {
            return false;
        }
    }
    return true;
}

private static String getNewKey (HashMap<String, Double> hashMap) {

    String alpha = "abcdefghilmnopqrstuvzyjkx";
    for (int j = 0 ; j < alpha.length() ; j++) {
        String k = alpha.substring(j,j+1);
        if (!hashMap.containsKey(k) & !Arrays.asList(usableMathMethods()).contains(k)) {
            return k;
        }
    }
    for (int j = 0 ; j < alpha.length() ; j++) {
        for (int i = 0 ; i < alpha.length() ; i++) {
            String k = alpha.substring(j,j+1)+alpha.substring(i,i+1);
            if (!hashMap.containsKey(k) & !Arrays.asList(usableMathMethods()).contains(k)) {
                return k;
            }
        }
    }
    throw new NullPointerException();
}

public static String[] usableMathMethods () {

    /*
     *  Only methods that:
     *  return a double type
     *  present one or two parameters (which are double type)
     */

    Method[] mathMethods = Math.class.getDeclaredMethods();
    ArrayList<String> usableMethodsNames = new ArrayList<>();
    for (Method method : mathMethods) {
        boolean usable = true;
        int argumentsCounter = 0;
        Class<?>[] methodParametersTypes = method.getParameterTypes();
        for (Class<?> parameter : methodParametersTypes) {
            if (!parameter.getSimpleName().equalsIgnoreCase("double")) {
                usable = false;
                break;
            }else {
                argumentsCounter++;
            }
        }
        if (!method.getReturnType().getSimpleName().toLowerCase().equals("double")) {
            usable = false;
        }
        if (usable & argumentsCounter<=2) {
            usableMethodsNames.add(method.getName());
        }
    }
    return usableMethodsNames.toArray(new String[usableMethodsNames.size()]);
}

private static boolean isDouble (String number) {
    try {
        Double.parseDouble(number);
        return true;
    }catch (Exception ex) {
        return false;
    }
}

private static String[] splitByLettersAndNumbers (String val) {
    if (!firstContainsOnlySecond(val, alphanumeric+"+-")) {
        throw new IllegalArgumentException("Wrong passed value: <<"+val+">>");
    }
    ArrayList<String> response = new ArrayList<>();
    String searchingFor;
    int lastIndex = 0;
    if (firstContainsOnlySecond(""+val.charAt(0), numeric+"+-")) {
        searchingFor = alphabetic;
    }else {
        searchingFor = numeric+"+-";
    }
    for (int j = 0 ; j < val.length() ; j++) {
        if (searchingFor.contains(val.charAt(j)+"")) {
            response.add(val.substring(lastIndex, j));
            lastIndex = j;
            if (searchingFor.equals(numeric+"+-")) {
                searchingFor = alphabetic;
            }else {
                searchingFor = numeric+"+-";
            }
        }
    }
    response.add(val.substring(lastIndex,val.length()));
    return response.toArray(new String[response.size()]);
}

private static void deleteValueIfPossible (String val, HashMap<String, Double> values, String function) {
    if (values.get(val) != null & function != null) {
        if (!function.contains(val)) {
            values.remove(val);
        }
    }
}

private static int contOccouranceIn (String howManyOfThatString, String inThatString) {
    return inThatString.length() - inThatString.replace(howManyOfThatString, "").length();
}
 }
 3
Author: Vinciuz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-15 21:45:15

Escribir tu propia biblioteca no es tan difícil como u podría ser. Aquí está el enlace para Shunting-yard algorithm con explicación paso a paso del algoritmo. Aunque, primero tendrás que analizar la entrada para los tokens.

Hay otras 2 preguntas que también pueden darle información: Convertir una Cadena en una Expresión Matemática? ¿Cuál es una buena biblioteca para analizar expresiones matemáticas en java?

 2
Author: Srneczek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:38

Como hay muchas respuestas, estoy agregando mi implementación encima del método eval() con algunas características adicionales como soporte para factorial, evaluación de expresiones complejas, etc.

package evaluation;

import java.math.BigInteger;
import java.util.EmptyStackException;
import java.util.Scanner;
import java.util.Stack;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class EvalPlus {
    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        System.out.println("This Evaluation is based on BODMAS rule\n");
        evaluate();
    }

    private static void evaluate() {
        StringBuilder finalStr = new StringBuilder();
        System.out.println("Enter an expression to evaluate:");
        String expr = scanner.nextLine(); 
        if(isProperExpression(expr)) {
            expr = replaceBefore(expr);
            char[] temp = expr.toCharArray();
            String operators = "(+-*/%)";
            for(int i = 0; i < temp.length; i++) {
                if((i == 0 && temp[i] != '*') || (i == temp.length-1 && temp[i] != '*' && temp[i] != '!')) {
                    finalStr.append(temp[i]);
                } else if((i > 0 && i < temp.length -1) || (i==temp.length-1 && temp[i] == '!')) {
                    if(temp[i] == '!') {
                        StringBuilder str = new StringBuilder();
                        for(int k = i-1; k >= 0; k--) {
                            if(Character.isDigit(temp[k])) {
                                str.insert(0, temp[k] );
                            } else {
                                break;
                            }
                        }
                        Long prev = Long.valueOf(str.toString());
                        BigInteger val = new BigInteger("1");
                        for(Long j = prev; j > 1; j--) {
                            val = val.multiply(BigInteger.valueOf(j));
                        }
                        finalStr.setLength(finalStr.length() - str.length());
                        finalStr.append("(" + val + ")");
                        if(temp.length > i+1) {
                            char next = temp[i+1];
                            if(operators.indexOf(next) == -1) { 
                                finalStr.append("*");
                            }
                        }
                    } else {
                        finalStr.append(temp[i]);
                    }
                }
            }
            expr = finalStr.toString();
            if(expr != null && !expr.isEmpty()) {
                ScriptEngineManager mgr = new ScriptEngineManager();
                ScriptEngine engine = mgr.getEngineByName("JavaScript");
                try {
                    System.out.println("Result: " + engine.eval(expr));
                    evaluate();
                } catch (ScriptException e) {
                    System.out.println(e.getMessage());
                }
            } else {
                System.out.println("Please give an expression");
                evaluate();
            }
        } else {
            System.out.println("Not a valid expression");
            evaluate();
        }
    }

    private static String replaceBefore(String expr) {
        expr = expr.replace("(", "*(");
        expr = expr.replace("+*", "+").replace("-*", "-").replace("**", "*").replace("/*", "/").replace("%*", "%");
        return expr;
    }

    private static boolean isProperExpression(String expr) {
        expr = expr.replaceAll("[^()]", "");
        char[] arr = expr.toCharArray();
        Stack<Character> stack = new Stack<Character>();
        int i =0;
        while(i < arr.length) {
            try {
                if(arr[i] == '(') {
                    stack.push(arr[i]);
                } else {
                    stack.pop();
                }
            } catch (EmptyStackException e) {
                stack.push(arr[i]);
            }
            i++;
        }
        return stack.isEmpty();
    }
}

Por favor, encuentre el gist actualizado en cualquier momento aquí. También comentar si hay algún problema. Gracias.

 1
Author: abubakkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-11 10:09:46

No hay nada que haga esto en JavaSE; tendrías que encontrar librerías de terceros o escribir las tuyas propias.

 0
Author: polygenelubricants,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 04:17:05

Con Java 9, tenemos acceso a jshell, así que uno puede escribir algo como esto:

import jdk.jshell.JShell;
import java.lang.StringBuilder;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Eval {
    public static void main(String[] args) throws IOException {
        try(JShell js = JShell.create(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {

            js.onSnippetEvent(snip -> {
                if (snip.status() == jdk.jshell.Snippet.Status.VALID) {
                    System.out.println("➜ " + snip.value());
                }
            });

            System.out.print("> ");
            for (String line = br.readLine(); line != null; line = br.readLine()) {
                js.eval(js.sourceCodeAnalysis().analyzeCompletion(line).source());
                System.out.print("> ");
            }
        }
    }
}

Ejecución de muestra:

> 1 + 2 / 4 * 3
➜ 1
> 32 * 121
➜ 3872
> 4 * 5
➜ 20
> 121 * 51
➜ 6171
>

Ligeramente OP, pero eso es lo que Java tiene actualmente para ofrecer

 0
Author: smac89,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-27 03:31:44