【问题标题】:Returns inside ifs confuse Javaifs 内部的返回混淆了 Java
【发布时间】:2011-12-20 14:53:09
【问题描述】:

我有这两种方法,Java 在 getNumEmails() 中找不到“返回”。它们都在同一个类中,只有静态方法

private static int posSymbol=0;
private static int cont=0;
private static String text=null;


private static int getPosSymbol(){
     posSymbol=text.indexOf('@',posSymbol);//if there is no symbol, returns -1
     return posSymbol;
}

//Main calls this method
public static int getNumEmails(String completeText){
     text=completeText;

     while(posSymbol!=(-1)){

         posSymbol=getPosSymbol();

         if(posSymbol!=(-1)){
              cont++;
              posSymbol++;
         }//close if
         else{
              return cont; //It seems that it doesn't reach the return always
         }//close else
         }//close while
}//close method

我知道解决方法很简单,删除“else”并把return cont;一段时间后。但我想知道为什么 Java 认为 getNumEmails() 可以结束而不返回任何内容。

【问题讨论】:

  • 如果 getPosSymbol() 的值为 -2 或从未为 -1,它肯定会退出而不返回...
  • 是什么让你认为它总是会返回一些东西? else 子句可能永远不会被执行。
  • @Kendrick。是的,但编译器不会进入那个级别的检查。它只是看到else
  • @Arkonor - 所以你知道,这段代码存在严重的潜在问题。最糟糕的是,如果您尝试使用此多线程。其中最烦人的是它不能运行两次(在某些情况下)。另外,不要放置闭括号 cmets;大多数现代 IDE 会突出显示开/关括号对,您的方法应该足够长以使它们成为必要,并且它们存在变得不同步的风险。
  • @Kendrick。 getPosSymbol 不能返回 -2 也不能返回永无止境的值,因为。 a) indexOf() 如果找到符号的匹配项,则返回 -1 或正值。 b)我怀疑它接收到的字符串不能有结尾(可能捕获在流中广播的文本或一些奇怪的东西,但在我的情况下,文本的来源是键盘输入)

标签: java if-statement return


【解决方案1】:

可以在 else 子句中找到返回值。问题是您需要为所有执行路径返回一个返回值,即使是 posSymbol 等于 -1 的路径,因为当 posSymbol 等于 -1 时,您永远不会进入 while 循环。

因此您需要在 while 语句之后返回。

【讨论】:

  • 但是在while循环内部的getPosSymbol()可以在while条件检查后返回-1值。
  • 但这不是您编写代码的方式。 while 语句的作用域是永远不会执行的,除非满足 while 子句中的条件。由于 return 语句在 while 范围内,因此不会执行。
  • 我可以向您保证,我尝试在 While 之前设置 posSymbol=0,但它仍然没有工作
  • 这不是重点。编译器无法推断它永远不会在任何顺序循环中离开 while 循环,因此它仍然需要在该范围之后的 return 语句。编译器不会进行任何分析来检查变量的条件是始终为真还是始终为假,它知道鉴于您有一段时间,它后面的任何语句中都应该有一个 return 语句,因为您的方法声明指出应该返回一个值。
【解决方案2】:

我想这是关于编译器抱怨This method must return a result of type int

虽然编译器有时可以确定函数是否会到达 return 语句,但情况并非总是如此。静态地确定程序的动态行为在数学上是不可能的。
这在计算机科学中被称为“停机问题”;在一般情况下,无法确定程序是否会终止。
因此,即使您可以确定该方法将始终到达您的 return 语句之一,编译器也可能无法这样做。

【讨论】:

  • 我怀疑程序在查找返回时可能会遇到问题,因为它只考虑了方法本身(没有方法之外的任何其他数据),或者它试图通过黑盒测试来验证对该返回的访问(使用随机值或其他东西)现在我知道了真相,谢谢。顺便说一句,我想知道编译器是否可以处理这段代码,即使它找不到返回(可能不是,但谁知道......)
  • 现在我正在考虑它。如果程序更复杂,我可能会遇到很多问题来寻找另一种解决方法。在这种情况下,我只需要在“while”之后加上“return”,但在另一个程序中这是不可行的
  • 顺便说一句,我怎样才能使用返回键而不添加评论XD
  • 正如其他人指出的那样,在这种特殊情况下,实际上存在一个从未遇到过 return 的执行路径。从技术上讲,编译器可以找到return,它不能确定所有的执行路径。在更复杂的算法中……嗯,解决这些问题只是编程的另一部分,不是吗?
  • 但是你无法避免“while”中的入口,在遇到“while”之前将posSymbol设置为零。我还尝试在此之前将其设置为零,但它仍然给我带来了问题
【解决方案3】:

Java 编译器无法静态(在编译时)验证 while 循环是否被执行(posSymbol 在第一次调用时可能是 -1)。因此出现错误。

一般来说,在成员变量中保持循环状态并不是一个好主意。如果多个线程执行您的方法(例如在 Web 服务器中)怎么办?从长远来看,如果您的代码不修改全局状态,则更容易追踪错误:

public static int getNumEmails(String completeText) {
    int count = 0;
    Matcher m = Pattern.compile("@").matcher(completeText);
    while (m.find()) {
        count++;
    }
    return count;
}

【讨论】:

  • 我不知道这些方法是如何工作的。请问,你能解释一下吗?顺便说一句,我从没想过多个用户同时运行这个程序。我必须在未来考虑到这一点。
  • 此代码尝试使用正则表达式查找completeText 中有多少@。你可以在这里查看:download.oracle.com/javase/7/docs/api/java/util/regex/….
【解决方案4】:

只需在“//close while”之后添加return 0;

【讨论】:

  • 该方法可能会在结束前返回 2 个不同的值。它可能会使整个程序崩溃。抱歉,这并不能解决我的问题。
  • 一个方法只能返回一个值。 Return 表示方法退出,不再运行。
  • 一个break只存在于for/while循环或switch/case条件之类的块中。
【解决方案5】:

不是答案,但这里有一个更安全的方法版本,没有静态变量。

//Main calls this method 
public static int getNumEmails(String completeText)
{
    int posSymbol=0, count=0;
    while(posSymbol!=(-1))
    {           
        posSymbol=completeText.indexOf('@',posSymbol); //if there is no symbol, returns -1
        if(posSymbol!=(-1))
        {
            ++count;
            ++posSymbol;
        }//close if
    }//close while
    return count;
}//close method 

【讨论】:

  • 这就是我最后所做的。我意识到 else 也意味着程序结束。因此,我可以将 return 放在 while 之后,以确保程序总是遇到 return。
  • @Kendrik - 同意,这样更安全。但是,将indexOf() 调用放在while 循环的条件检查中怎么样?
猜你喜欢
  • 2013-07-11
  • 1970-01-01
  • 2017-01-11
  • 2020-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-22
  • 1970-01-01
相关资源
最近更新 更多