关于java:在方法开头使用返回错误的编码实践?

Is using return at the start of method bad coding practice?

我发现自己在使用下面的练习,但每次使用它,我内心的某些东西都会有点畏缩。基本上,这是一个先决条件的参数测试,以确定是否应该做实际的工作。

1
2
3
4
5
6
7
public static void doSomething(List<String> things)
{
    if(things == null || things.size() <= 0)
        return;

    //...snip... do actual work
}


尽早返回是一种良好的做法。这样就可以执行和评估最少数量的代码。

不能运行的代码不能出错。

此外,它使函数更易于阅读,因为您不必处理所有不再适用的情况。

比较以下代码

1
2
3
4
5
6
7
8
9
private Date someMethod(Boolean test) {
  Date result;
  if (null == test) {
    result = null
  } else {
    result = test ? something : other;
  }
  return result;
}

VS

1
2
3
4
5
6
7
private Date someMethod(Boolean test) {

  if (null == test) {
    return null
  }
  return test ? something : other;
}

第二个比较短,不需要else,也不需要temp变量。

注意,在Java中,EDCOX1×1语句立即退出函数;在其他语言(例如Pascal)中,几乎等效的代码EDOCX1 OR 6不返回。由于这个事实,习惯上在Java方法的许多点返回。调用这个EDCOX1×7是忽略了那个特定的火车早就在Java中离开了站点的事实。

如果您无论如何都要在函数的多个点上退出一个函数,最好尽早退出


这是一个风格和个人喜好的问题。没什么问题。


据我所知-不。

为了便于调试,子例程、方法或函数中应该只有一个返回/退出点。

使用这种方法,您的程序可能会变得更长、更不可读,但是在调试期间,您可以在出口处放置一个断点,并始终看到返回的内容的状态。例如,您可以记录所有局部变量的状态—这对于故障排除可能非常有帮助。

看起来有两个"学校"——一个说"尽早返回",另一个说"一个程序中应该只有一个返回/退出点"。

我是第一个的支持者,尽管在实践中有时会跟随第二个,只是为了节省时间。

另外,不要忘记例外。通常情况下,您必须尽早从方法返回这一事实意味着您处于一个特殊的情况中。在您的示例中,我认为抛出异常更合适。


这个问题没有正确的答案,这是一个品味问题。

在上面的具体示例中,可能有更好的方法来强制执行前置条件,但我认为多个早期返回的一般模式类似于功能编程中的保护。

我个人对这种风格没有异议——我认为它可以产生更干净的代码。试图扭曲所有东西以获得一个单一的出口点可以增加冗长和降低可读性。


没有什么本质上的问题,但如果它让你畏缩,你可以扔一个IllegalArgumentException。在某些情况下,这更准确。但是,当您调用doSomething时,它可能会导致一系列代码出现这种情况:

1
2
3
try {
    doSomething(myList);
} catch (IllegalArgumentException e) {}


PMD似乎是这样认为的,你应该让你的方法一直运行到最后,但是,为了某些快速的健全性检查,我仍然使用过早的return语句。

它确实会稍微降低方法的可读性,但在某些情况下,它可能比添加另一个if语句或其他方法更好,以便在所有情况下运行该方法。


这是很好的做法。所以继续努力吧。


如果函数很长(比如20行或更多行),那么最好在开始时返回很少的错误条件,这样在读取函数的其余部分时,代码阅读器就可以专注于逻辑。如果函数很小(比如5行或更少),那么开头的返回语句可能会分散读者的注意力。

因此,决策应该主要基于函数是否变得更可读或更不可读。


如果您想避免方法中的"返回":也许您可以使用自己的异常子类,并在方法的调用中处理它?

例如:

1
2
3
4
5
6
public static void doSomething(List<String> things) throws MyExceptionIfThingsIsEmpty {
    if(things == null || things.size() <= 0)
        throw new MyExceptionIfThingsIsEmpty(1,"Error, the list is empty !");    

    //...snip... do actual work
}

编辑:如果不想使用"return"语句,可以在if()中执行相反的操作:

1
2
if(things != null && things.size() > 0)
// do your things


没有什么问题。就个人而言,我将使用else语句来执行函数的其余部分,并让它自然返回。


Java好的实践表明,尽可能经常地,返回语句应该是唯一的,并且在方法的末尾写入。要控制返回的内容,请使用变量。但是,对于从void方法返回,就像您使用的示例一样,我将执行签入,中间方法仅用于此目的。无论如何,不要把这个问题看得太严重了——像continue这样的关键字不应该根据Java好的实践来使用,但是它们在你的范围内。