为啥它给我一个返回丢失错误?
Posted
技术标签:
【中文标题】为啥它给我一个返回丢失错误?【英文标题】:Why is it giving me a return missing error?为什么它给我一个返回丢失错误? 【发布时间】:2021-03-11 11:35:39 【问题描述】:为什么这个方法总是告诉我它缺少一个返回语句?如果我删除 else 它告诉我返回 true 是不可达的。提前感谢您的帮助!
public static boolean Digit(String pass)
for (int i=0; i < pass.length(); i++ )
if (!Character.isDigit(pass.charAt(i)))
System.out.println("Must contain digits");
return false;
else
return true;
【问题讨论】:
【参考方案1】:为什么这个方法总是告诉我它缺少一个返回语句?
因为在for
循环之后有一种方法可以到达该点。考虑pass
长度为零的情况。
更一般地说,确定语句(或代码中的点)的可达性的规则在JLS 14.22 中列出。一个简单的for
循环的相关规则如下:
当且仅当以下至少一项为真时,基本的
for
语句才能正常完成:for
语句可达,存在条件表达式,且条件表达式不是值为 true 的常量表达式(第 15.29 节)。 有一个可到达的 break 语句退出for
语句。
在您的示例中,第一个要求得到满足。因此,for
循环可以正常完成。因此在for
循环之后有一个返回点。因此此时需要return
语句。
请注意,可达性规则并不依赖于 Java 编译器是否足够聪明地分析您的应用程序的逻辑,它们也不会让编译器自行决定是否聪明。因此,有一些 Java 示例可以正式证明一条语句不可访问,但规则说它仍然是可访问的,并强制编译错误。
(因此在您的示例中,编译器不需要推理您的代码不考虑零长度字符串。这是“人类水平”的推理。)
【讨论】:
【参考方案2】:它在抱怨,因为您在循环结束时缺少返回。您的方法可以在三种不同的情况下退出,即:
-
当字符串
pass
不为空且首字符不为
一个数字;
当字符串pass
不为空且首字符为数字时;
当字符串为空时!。
在代码中:
public static boolean Digit(String pass)
for (int i=0; i < pass.length(); i++ )
if (!Character.isDigit(pass.charAt(i)))
System.out.println("Must contain digits");
return false; // <--- can exit here
else
return true; // <-- can exit here
// <-- can exit here if the string pass is empty
您涵盖了前两种情况,但没有涵盖第三种情况(即,当字符串为空时)。
现在,由于 Java 规则 "for determining the reachability of a statement" 正如@Stephen C 首先指出的那样(并且解释得很好,并且也是改进我的答案的灵感来源)逻辑上单独覆盖这三种情况不会使您的代码编译干净。例如:
public static boolean Digit(String pass)
if(pass.isEmpty())
return false;
for (int i=0; i < pass.length(); i++ )
if (!Character.isDigit(pass.charAt(i)))
System.out.println("Must contain digits");
return false;
else
return true;
在上面的代码中,所有可能的退出点都被覆盖了,但是,我的 IDE 仍然抱怨缺少 return 语句。为什么?因为根据上述规则,这个循环可以正常完成,因此在 if 的末尾需要一个return
。但是,使用相同的语义相同的代码:
public static boolean Digit(String pass)
if(pass.isEmpty())
return false;
for (int i = 0; true; i++ )
if (!Character.isDigit(pass.charAt(i)))
System.out.println("Must contain digits");
return false;
else
return true;
它编译得很好,即使在循环结束时没有返回语句。为什么?因为基于上述规则,我的循环无法正常完成,因为它的条件表达式是true
,更多详细信息可以在here找到。公平地说,我的 IDE 一添加您的代码,就立即收到警告,'for' statement does not loop
。
总之,对于您的情况,您需要涵盖这三种情况,并在循环结束时有一个 return 语句,您可以阅读更多关于 here 或 @Stephen C 的答案,它很好地分解了它。
除此之外,您的方法并没有达到您想要的效果。您只是比较字符串的第一个数字,但您应该检查整个字符串,例如:
public static boolean Digit(String pass)
for (int i=0; i < pass.length(); i++ )
if (!Character.isDigit(pass.charAt(i)))
System.out.println("Must contain digits");
return false;
return !pass.isEmpty();
当您发现一个不是数字的字符或(在循环结束时)检查整个字符串后,您只想return
。如果字符串为空,我将返回 !pass.isEmpty();
以确保我们不会 return true
。使用当前代码,我们涵盖了所有退出点,即:
-
如果字符串只包含数字,您将到达语句
return !pass.isEmpty();
,因此到达return true
;
如果字符串至少包含一个非数字,您将到达return false;
;
如果字符串为空,您将到达 return !pass.isEmpty();
,然后到达 return false
。
附带说明,您应该将方法名称从 Digit
更改为 isAllDigits
,后者比前者更明确。
另一方面,使用 Java Streams,您可以将方法简化为:
public static boolean isDigit(String pass)
return !pass.isEmpty() && pass.chars().allMatch(Character::isDigit);
【讨论】:
感谢您的输入!我只是忘了把循环的括号加起来以上是关于为啥它给我一个返回丢失错误?的主要内容,如果未能解决你的问题,请参考以下文章
% url % 给我 NoReverseMatch 错误,而 reverse() 返回 url 就好了。为啥?