为什么它会给我一个缺少返回的错误



为什么这个方法一直告诉我它缺少一个返回语句?如果我去掉其他的,它告诉我返回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示例中,可以正式证明语句不可达,但规则表示它仍然可以访问,并强制执行编译错误。

(所以在你的例子中,编译器不需要推理你的代码没有考虑到零长度的字符串。这是"人类层面"的推理。(

它在抱怨,因为您在循环结束时错过了一个返回。您的方法可以在三种不同的场景中退出,即:

  1. 当字符串pass不为空并且第一个字符不是数字
  2. 当字符串CCD_ 11不为空并且第一个字符是数字时
  3. 当字符串为空时

代码:

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。使用当前代码,我们涵盖了所有退出点,即:

  1. 如果字符串只包含数字,则会到达语句return !pass.isEmpty();,从而到达return true
  2. 如果字符串至少包含一个非数字,则会达到return false;
  3. 如果字符串为空,则会到达return !pass.isEmpty();,从而到达return false

附带说明,您应该将方法的名称从Digit更改为isAllDigits,后者比前者更明确。

另一个附带说明是,使用Java Streams,您可以将方法简化为:

public static boolean isDigit(String pass){
return !pass.isEmpty() && pass.chars().allMatch(Character::isDigit);
}

相关内容

  • 没有找到相关文章

最新更新