Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 堆栈溢出的原因是什么?_Java_Android_Recursion_Stack Overflow - Fatal编程技术网

Java 堆栈溢出的原因是什么?

Java 堆栈溢出的原因是什么?,java,android,recursion,stack-overflow,Java,Android,Recursion,Stack Overflow,我正在用Java为Android应用程序编写一个函数,它使用StringBuilder生成字符串的所有排列 每当函数运行时,程序立即终止,DDMS(Dalvic虚拟机调试工具)声称我的函数中存在堆栈溢出 private void reorder(String reorder_this, StringBuilder in_this){ for(int i = 0; i < reorder_this.length(); i++) { if(i == reord

我正在用Java为Android应用程序编写一个函数,它使用
StringBuilder
生成字符串的所有排列

每当函数运行时,程序立即终止,DDMS(Dalvic虚拟机调试工具)声称我的函数中存在堆栈溢出

private void reorder(String reorder_this, StringBuilder in_this){

    for(int i = 0; i < reorder_this.length(); i++)
    {
        if(i == reorder_this.length())
        {
            in_this.append(System.getProperty("line.separator"));
        }
        else
        {
            in_this.append(reorder_this.charAt(i));
            reorder(reorder_this.substring(0, i) + reorder_this.substring(i), in_this);
        }
    }
}
private void reorder(字符串重新排序\u this,StringBuilder在\u this中){
对于(int i=0;i
您可以看到,我对这个问题采取了递归的方法,我相信最终会用输入字符串的所有可能排列填充字符串生成器,每个排列后面都是换行符


有人知道是什么导致堆栈溢出吗?

简而言之,除非字符串长度为0,否则函数无法终止

您的方法首先将
i
设置为0,并测试
i
是否小于第一个参数的长度。如果是(除空字符串外的所有字符串都是这种情况),则会立即递归,因为不能严格小于长度等于长度。在递归调用中,传入一个长度完全相同的字符串(正如Thilo所指出的,实际上是完全相同的字符串)。这表明了算法的第二个问题:递归算法应该对每个递归调用的“较小”参数进行操作


在这里获取
StackOverflowException
并不需要很长时间。每个递归调用都会推送一个新的堆栈帧。

简而言之,除非字符串的长度为0,否则函数无法终止

您的方法首先将
i
设置为0,并测试
i
是否小于第一个参数的长度。如果是(除空字符串外的所有字符串都是这种情况),则会立即递归,因为不能严格小于长度等于长度。在递归调用中,传入一个长度完全相同的字符串(正如Thilo所指出的,实际上是完全相同的字符串)。这表明了算法的第二个问题:递归算法应该对每个递归调用的“较小”参数进行操作


在这里获取
StackOverflowException
并不需要很长时间。每次递归调用都会推送一个新的堆栈帧。

我认为问题在于这一行:

reorder(reorder_this.substring(0, i) + reorder_this.substring(i), in_this);

reorder\u this.substring(0,i)+reorder\u this.substring(i)
将生成一个相当于
reorder this
的字符串。我认为问题在于这一行:

reorder(reorder_this.substring(0, i) + reorder_this.substring(i), in_this);

reorder\u this.substring(0,i)+reorder\u this.substring(i)
将生成一个字符串,相当于
reorder this

Java中任何堆栈溢出的原因都是无限递归

private void reorder(String reorder_this, StringBuilder in_this){
    for(int i = 0; i < reorder_this.length(); i++)
    {
        if(i == reorder_this.length())
        {
private void reorder(字符串重新排序\u this,StringBuilder在\u this中){
对于(int i=0;i

通过构造,此块是不可访问的。因此您的终止条件永远不会满足。

Java中任何堆栈溢出的原因都是无限递归

private void reorder(String reorder_this, StringBuilder in_this){
    for(int i = 0; i < reorder_this.length(); i++)
    {
        if(i == reorder_this.length())
        {
private void reorder(字符串重新排序\u this,StringBuilder在\u this中){
对于(int i=0;i

通过构造,无法访问此块。因此,您的终止条件永远不会满足。

您是否使用一个小字符串(如“ABC”)来跟踪执行过程?(我的意思是“手动”跟踪,或在必要时,记录……但“玩电脑”确实有帮助。)我在nested for循环中发现了一个更有效的解决方案。我最近一直在使用scheme,并且一直停留在递归范式中。非尾部递归函数的效率通常较低;递归往往因其通信方式而大放异彩,而不一定是因为其执行方式。您是否用一个小字符串(如e“ABC”?(我的意思是“用手”追踪,或在必要时,记录……但“玩电脑”确实有帮助。)我在嵌套for循环中找到了一个更有效的解决方案。我最近一直在使用scheme,并且一直停留在递归范式中。非尾部递归函数的效率通常较低;递归之所以能发光,是因为它的通信方式,而不一定是它的执行方式。是的,
重新排序\u this.substring(0,I)+reorder\u this。子字符串(i)
将与
reorder\u this
相同。在这种情况下,它甚至不会到达。0永远不会<0。@EJP,我认为我的声明是正确的,因为该方法只能在for循环完成时终止。这就是我所称的“基本情况”虽然我的术语可能令人困惑,因为很容易将“基本情况”作为if子句的内容。因为OP在for循环中前进之前递归,“基本情况”除非原始字符串为空,否则永远无法完成循环。因此,是的,if语句的真实部分永远无法达到,正如我相信您所指出的。但真实部分不是我所说的基本情况,因为它在循环中。啊,我明白了。我的问题根源于我对子字符串函数的误解。看起来与第二个参数类似,它实际上指示指定的索引之前的索引。@Ray Toal它是基本情况,因为它是不递归的。循环与此无关。True,
reorder\u this.substring(0,i)+reorder\u this.substring(i)
将与
重新排序\u此
相同。在这种情况下,它甚至不会到达。0永远不会<0。@EJP,我认为我的声明是正确的,因为该方法只能在for循环完成时终止。