【问题标题】:StackOverFlowError in Java postfix calculatorJava 后缀计算器中的 StackOverFlowError
【发布时间】:2010-03-10 20:26:59
【问题描述】:

下面的类被另一个程序使用。当它被访问时,它会抛出一个 StackOverFlowError。这是我在大学里必须做的一个后缀计算器的一部分。

任何帮助将不胜感激,在此先感谢您。我是 Java 新手,不知道该怎么做。

代码:

import java.util.Queue;
import java.util.Stack;

public class MyPostfixMachine implements PostfixMachineInterface {

    MyMathOperations mmo = new MyMathOperations();
    MyPostfixMachine mpm = new MyPostfixMachine();

    public String evaluate(Queue q) {
        if (q.isEmpty()) {//if the input is empty, terminate the program
            System.exit(0);
        }
        if (q.size() == 1) {//if there is only one number in the queue, return it as the solution
            if (mpm.isParsableToDouble(String.valueOf(q.remove()))) {
                return String.valueOf(q.remove());
            }
        }
        Stack<String> finalxp = new Stack<String>();//create an empty stack
        if (mpm.isParsableToDouble(String.valueOf(q.remove()))) {//if first element of queue q is a number,push it into the stack
            finalxp.push(String.valueOf(q.remove()));
        } else {//depending on the operator perform the corresponding operations
            if (q.remove() == "+") {
                String str = String.valueOf(finalxp.pop());
                String str2 = String.valueOf(finalxp.pop());
                finalxp.push(mmo.addition(str, str2));
            }
            if (q.remove() == "-") {
                String str = String.valueOf(finalxp.pop());
                String str2 = String.valueOf(finalxp.pop());
                finalxp.push(mmo.substraction(str, str2));
            }
            if (q.remove() == "*") {
                String str = String.valueOf(finalxp.pop());
                String str2 = String.valueOf(finalxp.pop());
                finalxp.push(mmo.product(str, str2));
            }
            if (q.remove() == "/") {
                String str = String.valueOf(finalxp.pop());
                String str2 = String.valueOf(finalxp.pop());
                finalxp.push(mmo.division(str, str2));
            }
            if (q.remove() == "fibo") {
                String str = String.valueOf(finalxp.pop());
                finalxp.push(mmo.fibonacci(str));
            }
            if (q.remove() == "fac") {
                String str = String.valueOf(finalxp.pop());
                finalxp.push(mmo.factorial(str));
            }
            if (q.remove() == "han") {
                String str = String.valueOf(finalxp.pop());
                finalxp.push(mmo.hanoi(str));
            }
        }
        return String.valueOf(finalxp.pop());
    }

    public boolean isParsableToDouble(String candidate) {
        try {
            Double.parseDouble(candidate);
            return true;
        } catch (NumberFormatException nfe) {
            return false;
        }
    }
}





public class MyMathOperations implements MathOperationsInterface {

public String addition(String s1, String s2) {

    double A = Double.parseDouble(s1);
    double B = Double.parseDouble(s2);

    return String.valueOf((A + B));
}

public String substraction(String s1, String s2) {
    double A = Double.parseDouble(s1);
    double B = Double.parseDouble(s2);

    return String.valueOf((A - B));
}

public String product(String s1, String s2) {
    double A = Double.parseDouble(s1);
    double B = Double.parseDouble(s2);

    return String.valueOf((A * B));
}

public String division(String s1, String s2) {
    double A = Double.parseDouble(s1);
    double B = Double.parseDouble(s2);

    return String.valueOf((A / B));
}

public String fibonacci(String s) {
    int n = Integer.parseInt(s);
    return String.valueOf(fibo(n));
}

public int fibo(int f) {
    if (f < 0) {
        throw new IllegalArgumentException("Cannot apply Fibonacci method");
    } else if (f == 0) {
        return 0;
    } else if (f == 1) {
        return 1;
    } else {
        return fibo(f - 1) + fibo(f - 2);
    }

}

public String hanoi(String s) {
    int a = Integer.parseInt(s);
    int han = 0;
    if (a < 0) {
        throw new IllegalArgumentException("Not a valid integer");
    } else {
        han = (int) Math.pow(2, a) - 1;
    }
    return String.valueOf(han);
}

public String factorial(String s) {
    int a = Integer.parseInt(s);

    if (a < 0) {
        throw new IllegalArgumentException("Incorrect argument for factorial operatiion");
    }
    switch (a) {
        case 0:
        case 1:
            return String.valueOf(1);
        default:

            int res = a;
            while (true) {
                if (a == 1) {
                    break;
                }

                res *= --a;
            }
            return String.valueOf(res);
    }

}

private static double pDouble(String s) {
    double res = 0d;
    try {
        res = Double.parseDouble(s);
    } catch (NumberFormatException e) {
        System.exit(1);
    }

    return res;
}

}

【问题讨论】:

  • 您应该添加StackOverflowError 的堆栈跟踪,以便轻松查看哪一行失败。
  • 您得到的异常将有一个堆栈跟踪,准确显示堆栈溢出发生的位置。 (至少,我希望如此。)您没有将代码发布到您的“MyMathOperations”代码中......
  • 您是否在大量拨打fibo

标签: java queue calculator stack-overflow postfix-notation


【解决方案1】:

问题是您的 class MyPostfixMachine 有一个私有字段 MyPostfixMachine mpm,它是用 new MyPostfixMachine 初始化的。由于这个新的 MyPostfixMachine 也有一个私有字段 MyPostfixMachine mpm ,它是用新的 MyPostfixMachine 初始化的......你明白了。 :) 这会一直持续下去(或者直到你的堆栈已满)。

这是有问题的代码:

public class MyPostfixMachine implements PostfixMachineInterface {

    MyMathOperations mmo = new MyMathOperations();
    MyPostfixMachine mpm = new MyPostfixMachine(); // problem is here

    // ...
}

我认为您可以简单地删除私有字段 mpm。只需调用当前实例上的方法。所以而不是:

if (mpm.isParsableToDouble(String.valueOf(q.remove()))) {...}

你可以简单地写:

if (isParsableToDouble(String.valueOf(q.remove()))) {...}

或(等效但更明确):

if (this.isParsableToDouble(String.valueOf(q.remove()))) {...}

无论如何,只要删除私有字段 mpm,StackOverflowException 就应该消失了。

【讨论】:

  • 不错的收获!很高兴我把“除非我错过了什么”放在我自己的回答中。 :-)
  • 天哪,这是我从未怀疑会导致错误的单段代码,非常感谢!我现在可以继续我的任务了。再次感谢您。
【解决方案2】:

我不确定你是如何得到 StackOverflowError 的(我在这段代码中没有看到任何循环或递归),但一个明确的问题是你过度使用了 Queue.remove()。每次查看 if 子句中的队列时,您都会删除第一个元素——我希望这段代码会被 NoSuchElementExceptions 吐出。

更不用说所有EmptyStackExceptions,你应该从一个空的Stack弹出。

所以我想说....

  1. 当您应该调用 `peek()` 时,请退出调用 `remove()`。
  2. 退出从空堆栈弹出;您想从输入队列中提取这些值,是吗?
  3. 给您 `StackOverFlowError` 的问题在别处。 (除非我忽略了某些东西——总是可能的!)寻找循环或递归调用。

【讨论】:

    猜你喜欢
    • 2012-08-29
    • 2017-01-27
    • 1970-01-01
    • 2018-03-20
    • 1970-01-01
    • 2012-04-11
    • 2016-07-10
    • 2012-06-26
    • 2012-04-05
    相关资源
    最近更新 更多