Java在if-else ladder中要求即使在返回值时也要返回一个值。

huangapple go评论58阅读模式
英文:

Java is asking to return a value even when the value is returned in the if-else ladder

问题

以下是翻译好的部分:

我正在尝试在Java中编写AVL树,但某些事情刚刚动摇了我对基本编程的理解。为什么Java要求我在if-else梯队的else块中已经有return语句时返回一个值。我尝试调试,它按预期工作,它从不进入if-else块之外的返回语句。我一直在使用Java,但从未意识到这一点。我甚至不确定这是否一直存在还是新添加的内容?我还阅读了一些博客,它们说如果你已经在else块中返回了值,就不必再返回一个值。

我得到的错误是我跳过了最后一个返回语句。
线程中的异常"main"java.lang.Error:未解决的编译问题:
这个方法必须返回类型为AVLNode的结果。

https://javahungry.blogspot.com/2019/12/missing-return-statement-in-java.html
查看此链接上的最后一个示例。

public class AVL
{
AVLNode root;

private AVLNode insert (AVLNode current, int val)
{
	if (current == null)
	{
		return new AVLNode(val, 0, null, null);
	}
	else if (val < current.val)
	{
		current.left = insert(current.left, val);
	}
	else if (val > current.val)
	{
		current.right = insert(current.right, val);
	}
	else
	{
		return current;
	}
	return current;		// 我不想返回你 ////		
}

public void add (int val)
{
	this.root = insert(this.root, val);
}

}

英文:

I was trying to code AVL tree in java and something has just shaken my understanding of basic programming. Why does Java force me to return a value when I already have a return statement in the else block of the if-else ladder. I tried debugging and it works as expected, it never goes to the returns statement outside the if-else blocks. I have been working on java and never realized this. I am not even sure if this was always there or is it something new? I also read a few blogs which say that you don't have to return a value if you have returned it from the else block.

The error which I get is I skip the last return statement.
Exception in thread &quot;main&quot; java.lang.Error: Unresolved compilation problem: 
	This method must return a result of type AVLNode

https://javahungry.blogspot.com/2019/12/missing-return-statement-in-java.html
checkout the last example on this link.

public class AVL 
{
	AVLNode root;
	
	private AVLNode insert ( AVLNode current,int val)
	{
		if ( current == null)
		{
			return new AVLNode(val, 0, null, null);
		}
		else if ( val &lt; current.val)
		{
			current.left = insert ( current.left, val);
		}
		else if ( val &gt; current.val)
		{
			current.right = insert ( current.right, val);
		}
		else
		{
			return current;
		}
		return current;		// I don&#39;t want to return you ////		
	}


public void  add ( int val)
	{
		this.root = insert ( this.root, val);
	}

答案1

得分: 1

你可以使用以下方式之一:

else
{
    return current;
}

或者

return current;

所以在我看来,你的 "if-else" 是一种条件设置变量 "current" 正确值的方式,因此将 "else" 用于返回目的有点奇怪,所以你的代码可以重构为以下方式:使用 if-else 捕获条件中的所有可能情况,在每种情况下设置变量,然后完成后返回该值,如下所示:

private AVLNode insert (AVLNode current, int val)
{
    if (current == null)
    {
        return new AVLNode(val, 0, null, null);
    }
    else if (val < current.val)
    {
        current.left = insert(current.left, val);
    }
    else if (val > current.val)
    {
        current.right = insert(current.right, val);
    }
    
    return current;
}
英文:

you either use

else

    {
        return current;
    }

or

    return current;   

so in my opinion your "if-else" is a conditional way to set the correct value for the variable "current" so using "else" for returning purposes is kind of strange,so you code can be refactored as this: use the if-else to catch all possible cases in the condition, set the variable in ever case and then, when you are done, return the value, like:

private AVLNode insert ( AVLNode current,int val)
{
    if ( current == null)
    {
        return new AVLNode(val, 0, null, null);
    }
    else if ( val &lt; current.val)
    {
        current.left = insert ( current.left, val);
    }
    else if ( val &gt; current.val)
    {
        current.right = insert ( current.right, val);
    }
         
    return current;     
}

答案2

得分: 1

你出现这个错误的原因是因为如果你没有最后的return语句,而是进入了其中一个if块,就永远不会进入else,因此也不会触发return语句。

尝试使用current.valval都指定但值不同的情况,例如current.val = 2val = 1,逐步执行代码。

在这种情况下,执行将跳过第一个if(因为current不是null),然后进入第二个if块(因为val > current.val)。因为已满足了一个if条件,我们将跳过后面的else ifelse,然后执行最后的return语句。如果没有那个语句,就不会返回任何内容。

之所以与你提到的例子不同,是因为那个例子在if块和else块中都有return,所以无论发生什么,你都会遇到return语句。你可以通过在两个else if块中都添加return current;来实现相同的效果,不过只在最后添加一个return会更清晰简洁。

基本上,如果你有一系列的if...else if...else if...else,执行过程只会访问其中一个块。无论哪个代码路径被执行,都必须始终有一个return

英文:

The reason you get this error is because if you didn't have the final return statement, and ended up inside one of the if blocks, you'd never hit the else and therefore never hit a return statement.

Try stepping through the code with any case where current.val and val are both specified, but are two different values, for example current.val = 2 and val = 1.

In this case the execution will skip over the first if (because current is not null), and then go into the second if block (because val &gt; current.val). Because one of the if conditions has been met, we will skip over the following else if and the else, and hit the final return statement. If that statement weren't there, we'd never return anything.

The reason this is different from the example you cite is because that example has a return in both the if and the else blocks, so whatever happens you always encounter a return statement. You could achieve the same by adding return current; inside both else if blocks, although it's far cleaner just to have the single return at the end.

Basically, if you have a collection of if...else if...else if...else the execution will only ever visit one of the blocks. Whichever path through the code gets executed must always have a return.

答案3

得分: 0

Clean code的一个原则是"方法应该只有一个返回语句",所以即使你的代码是正确的,你也可以像这样做会更好:

private AVLNode insert (AVLNode current, int val)
{
    AVLNode returningObject = current;

    if (current == null) {
        current = new AVLNode(val, 0, null, null);
    } else if (val < current.val) {
        current.left = insert(current.left, val);
    } else if (val > current.val) {
        current.right = insert(current.right, val);
    }

    return returningObject;       
}

这样可以解决问题:// 我不想要返回值 ////

但是你遇到的问题是因为Java足够"聪明",在运行代码之前会检查所有的语句,如果你把所有的"返回"放在块语句中,Java会知道存在一种情况,即你的语句可能无法实现,并强制你从方法中始终返回某些东西。

这是我能够简单解释的方式。

英文:

One of the principle of Clean code is method should have only one return statement so even if your code is good and working you could do it would be better if you do something like this

private AVLNode insert ( AVLNode current,int val)
    {
       AVLNode returningObject = current;

        if ( current == null) {
            current = new AVLNode(val, 0, null, null);
        } else if ( val &lt; current.val) {
            current.left = insert ( current.left, val);
        } else if ( val &gt; current.val) {
            current.right = insert ( current.right, val);
        }
   
        return returningObject ;       
    }

And that solve the issue with // I don&#39;t want to return you ////

But you problem appears cause Java is smart enough to check all your statements before you run your code, and if you put all your returns into block statements Java knows that there is situation where your statements can be not achieved and force you to always return something from the method.

This is the simplest way I can explain it.

答案4

得分: 0

你所有对insert()的递归调用,迟早都会结束在包含return的分支之一(或者为了讨论方便,让我们假设是这样的)。我认为你的误解在于认为这就足够了。但是每个递归调用级别都必须有自己的return

所以这两行

current.left = insert(current.left, val);
/* ... */
current.right = insert(current.right, val);

每一行也需要一个return,以便从进行调用的级别返回,最深嵌套的递归调用级别的隐含return仅适用于该级别。

英文:

All of your recursive calls to insert () sooner or later end up on one of the branches which contain a return (or let's assume that for the sake of the discussion).
I think that your misconception is that this is enough.
But each level of recursive call has to get its own return.

So these two lines

current.left = insert ( current.left, val);
/* ... */
current.right = insert ( current.right, val);

each also need a return, in order to return from the level which did the calling, the implied return at the deepest nested recursive call level is only for that level.

答案5

得分: 0

而且不仅仅适用于Java。当您拥有类似于原始帖子中的嵌套结构时,当它匹配第一个“if”并开始沿着嵌套的if-then-else-if阶梯执行时,它绝对不会以某种方式跳转到匹配顶层“if”语句的“else”部分,因为它已经评估过该条件并选择了其执行路径。

您要测试的条件是独立且无关的,因此根本没有必要使用```else```结构。一旦我们处理了空值情况并返回了一个新的AVLNode,它们只是简单的无关的```if```语句,有条件地修改```current```的状态。

```java
private AVLNode insert ( AVLNode current, int val) {

   if (current == null) {
      return new AVLNode(val, 0, null, null);
   }

   if (val < current.val) {
      current.left = insert(current.left, val);
   }

   if (val > current.val) {
      current.right = insert(current.right, val);
   }

   // 当 val == current.val 时不会有任何变化,这是正确的吗?

   return current;      
}
英文:

And not just for Java, either. When you have a nested structure like the one in the OP, when it matches the first 'if' and starts down your nested if-then-else-if ladder, then it is never going to somehow fall through to the 'else' that matches the top-level 'if' statement because it has already evaluated that condition and chosen its execution path.

The conditions you are testing for are independent and unconnected, so there is no need for the else construct at all. Once we have dealt with the null case and returned a new AVLNode, they are just simple unconnected if statements that conditionally modify the state of current.

private AVLNode insert ( AVLNode current, int val) {

   if (current == null) {
      return new AVLNode(val, 0, null, null);
   }

   if (val &lt; current.val) {
      current.left = insert(current.left, val);
   }

   if (val &gt; current.val) {
      current.right = insert(current.right, val);
   }

   // nothing changes when val == current.val, is this correct?

   return current;      
}

huangapple
  • 本文由 发表于 2020年7月31日 15:32:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/63187609.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定