为什么这个方法一直告诉我它缺少一个返回语句?如果我去掉其他的,它告诉我返回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;
}
}
为什么这个方法一直告诉我它缺少一个返回语句?
因为有一种方法可以到达for
循环之后的点。考虑pass
的长度为零的情况。
更一般地,用于确定语句(或代码中的点(的可达性的规则在JLS 14.22中列出。简单for
循环的相关规则如下:
基本
for
语句可以正常完成,当且仅当以下至少一项为真:
for
语句是可达的,存在条件表达式,并且条件表达式不是值为true的常量表达式(§15.29(- 有一个可到达的break语句退出
for
语句
在您的示例中,满足了第一个要求。因此,for
循环可以正常完成。因此,在for
循环之后有一个返回点。因此,此时需要return
语句。
请注意,可达性规则并不取决于Java编译器是否足够聪明来分析应用程序的逻辑,它们也没有赋予编译器明智的判断权。因此,在Java示例中,可以正式证明语句不可达,但规则表示它仍然可以访问,并强制执行编译错误。
(所以在你的例子中,编译器不需要推理你的代码没有考虑到零长度的字符串。这是"人类层面"的推理。(
它在抱怨,因为您在循环结束时错过了一个返回。您的方法可以在三种不同的场景中退出,即:
- 当字符串
pass
不为空并且第一个字符不是数字 - 当字符串CCD_ 11不为空并且第一个字符是数字时
- 当字符串为空时
代码:
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规则"用于确定语句"的可达性正如@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
,所以可以在这里找到更多关于它的详细信息。公平地说,我的IDE一添加您的代码,就立即收到了'for' statement does not loop
的警告。
总之,对于您的案例,您需要涵盖这三个场景,并在循环结束时有一个return语句,您可以在这里阅读更多信息,或者使用@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);
}