首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >正在尝试创建图形计算器,在线程"AWT-EventQueue-0“java.lang.StackOverflowError中收到异常

正在尝试创建图形计算器,在线程"AWT-EventQueue-0“java.lang.StackOverflowError中收到异常
EN

Stack Overflow用户
提问于 2018-06-15 02:40:23
回答 1查看 70关注 0票数 1

我正在试着做一些像Desmos这样的东西。我成功地让它绘制了一些基本的函数,如e^x,sin (x),x^2,1/x等。问题是当我试图用另一个函数作为参数来绘制一个函数时。例如,我尝试绘制sin (2x),它显示了前面提到的错误Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError

我试着做了很多事情,但都没有奏效。以下是这里使用的代码部分:(其中一些是塞尔维亚语,但我将翻译必要的部分):

来自主类的

代码语言:javascript
复制
public static void main(String[] args) 
{
/*...*/
Funkcija f1 = new LinearnaFunkcija(2, 0);
Funkcija f = new SinFunkcija();
/*...*/
}

Funkcija (function)类

代码语言:javascript
复制
public Double vrednost(Double arg)
{
    if(arg.isNaN() || arg == null || arg.isInfinite())
    {
        return Double.NaN;
    }
    if (this.arg.equals(new LinearnaFunkcija(1,0)))
    {
        this.arg = null;
    }
    return vrednost(this.arg.vrednost(arg));
}

注意:"vrednost“表示"value”

来自LinearnaFunkcija (线性函数)类

代码语言:javascript
复制
public class LinearnaFunkcija extends Funkcija
{
    private double k;
    private double n;
    public LinearnaFunkcija(double k, double n)
    {
        this.k = k;
        this.n = n;
    }
    public LinearnaFunkcija(double arg)
    {
        this.k = 0;
        this.n = arg;
    }
    public Double vrednost(Double arg)
    {
        if(this.arg != null)
        {
            super.vrednost(arg);
        }
        return k * arg + n;
    }
    /*...*/
}

来自SinFunkcija (正弦函数)类

代码语言:javascript
复制
public Double vrednost(Double arg)
    {
        if(this.arg != null)
        {
            super.vrednost(arg);
        }
        return Math.sin(arg);
    }

绘制函数的方法

代码语言:javascript
复制
public void draw(Graphics g)
{
    /*...*/
        Double xc, yc;
        int xp;
        int[] x = new int[1000010];
        int[] y = new int[1000010];
        int count = 0;
        for(xp = 0; xp < polje.getWidth(); xp++, count++)
        {
            xc = polje.getXValue(xp);
            yc = f.vrednost(xc);
            if(yc.isNaN() || yc.isInfinite() || polje.getYPos(yc) < 0)
            {
                g.drawPolyline(x, y, count);
                count = -1;
                continue;
            }
            x[count] = xp;
            y[count] = polje.getYPos(yc);   
        }
        g.drawPolyline(x, y, count);
    }
}

(注意:poljeJPanel子类的一个实例)

所以当我运行这段代码时,我会得到

代码语言:javascript
复制
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
    at java.io.FileOutputStream.write(Unknown Source)
    at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
    at java.io.BufferedOutputStream.flush(Unknown Source)
    at java.io.PrintStream.write(Unknown Source)
    at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
    at sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source)
    at java.io.OutputStreamWriter.flushBuffer(Unknown Source)
    at java.io.PrintStream.newLine(Unknown Source)
    at java.io.PrintStream.println(Unknown Source)
    at funkcije.LinearnaFunkcija.vrednost(LinearnaFunkcija.java:26)
    at funkcije.Funkcija.vrednost(Funkcija.java:30)
    at funkcije.SinFunkcija.vrednost(SinFunkcija.java:42)
    at funkcije.Funkcija.vrednost(Funkcija.java:30)
    at funkcije.SinFunkcija.vrednost(SinFunkcija.java:42)
    at funkcije.Funkcija.vrednost(Funkcija.java:30)
    at funkcije.SinFunkcija.vrednost(SinFunkcija.java:42)
    at funkcije.Funkcija.vrednost(Funkcija.java:30)
    at funkcije.SinFunkcija.vrednost(SinFunkcija.java:42)
    at funkcije.Funkcija.vrednost(Funkcija.java:30)

,等等。

将显示窗口(JFrame),但该窗口为空白。

有人知道是什么导致了这个问题吗?根据错误,这两个方法显然是递归地相互调用,这将造成一个永无止境的堆栈,即堆栈溢出。但这是不应该发生的。其他人知道问题出在哪里吗?

如果你需要更多的代码,请告诉我。

EN

回答 1

Stack Overflow用户

发布于 2018-06-15 04:00:29

让我为Function推荐一个更好的设计,在这个设计中可以避免递归调用和对super的调用。如果实际的计算逻辑(例如,用于SinFunkcijareturn Math.sin(arg),用于LinearnaFunkcijak * arg + n等)与处理特殊情况和嵌套函数调用是分开的。

其中一种方法是应用模板方法模式,如下所示:

代码语言:javascript
复制
public abstract class Function {

    private final Function nested;

    public Function(Function nested) {
        this.nested = nested; //a nested function, possibly null 
    }

    public void calculate(Double argument) {
        if (this.nested != null) { //first, try calculating the inner function
            argument = this.nested.calculate(argument);
        }
        if (argument == null || argument.isNaN() || argument.isInfinite()) { //then, check if argument is valid; be careful to check argument == null before you try and invoke methods on it! 
            return Double.NaN;
        }
        return calculateForValidValue(argument); //at this point, you're 100% sure arg is a valid Double
    }

    protected abstract Double calculateForValidValue(Double argument);
} 

然后,子类变成:

代码语言:javascript
复制
public class SinFunkcija extends Function {
    protected Double calculateForValidValue(Double argument) {
        return Math.sin(argument); //as simple as that
    }
}

您可以通过嵌套构造函数调用来嵌套函数:new SinFunkcija(new LinearnaFunkcija(null, 2, 0)).calculate(3.0)

注意,‘最里面’函数的参数是简单的null。如果您想要使用空对象模式(我认为这就是this.arg.equals(new LinearnaFunkcija(1,0))代码行的内容),您可以使用一个特殊的Noop函数:

代码语言:javascript
复制
public class Noop extends Function {
    public Noop() {
        super(null); //no nested function here
    }

    //this is the only case when we want to override calculate
    public void calculate(Double argument) {
        return argument; 
    }

    protected Double calculateForValidValue(Double value) { return null; }
}

然后,您可以编写像这样的函数:new SinFunkcija(new LinearnaFunkcija(new Noop(), 2, 0)).calculate(3.0),并跳过Function中的if (this.nested != null) {检查。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50863927

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档