繁体   English   中英

编程新手 - ***更新***实践问题抛出 StringIndexOutOfBoundsException

[英]New to programming - ***Updated*** PracticeProblem throwing StringIndexOutOfBoundsException

我正在尝试自学 Java,最近我一直在用内置编译器做在线练习题。 除了字符串长度小于 2 的两个条件外,我的代码在大多数情况下都运行良好。

这个特定练习题的 URL 是: http : //codingbat.com/prob/p123384

问题:给定一个字符串,返回一个新字符串,其中第一个和最后一个字符已交换。

例子

frontBack("code") should be→ "eodc"
frontBack("a") should be→ "a"
frontBack("ab") should be→ "ba"

这是我的代码:

    public String frontBack(String str) {

  char firstChar = str.charAt (0);

  char lastChar = str.charAt (str.length()-1);

  String middle = str.substring(1, str.length()-1);

    if (str.length()>=3){

  return lastChar + middle + firstChar;

  }

 else {

return new StringBuilder(str).reverse().toString();

}

}

这是错误的两个条件

frontBack("a") should be→ "a"

"Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: -1 (line number:4)"


frontBack("") should be→ ""

"Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 0           (line number:2)"

这是解决方案,有效的代码

public String frontBack(String str) {
  if (str.length() <= 1) return str;

  String mid = str.substring(1, str.length()-1);

  // last + mid + first
  return str.charAt(str.length()-1) + mid + str.charAt(0);
}

我的代码和解决方案有什么区别?

任何帮助都会很棒。 我对此感到困惑,因为我的 else 语句只是返回原始字符串。 为什么任何变量(frontChar、middle、lastChar)会影响我返回的原始字符串? 提前致谢!

首先我要感谢所有帮助过我的人!*

我重新编写了我的代码并将其缩小到一个简单的区别。 区别在于放置显式语句以说明等于或小于 1 的字符串。 这显然不能通过 catch-all else 语句隐式处理。 仍然不确定为什么? 这是相同的代码,只有一个细微的区别; 显式与隐式

此代码有效...如果字符串长度小于或等于 1,则显式返回 str。

public String frontBack(String str) {

  // This line below is the only difference 

  if (str.length() <= 1) {
   return str;
  }

  char firstChar = str.charAt (0);

  char lastChar = str.charAt (str.length()-1);

  String middle = str.substring(1, str.length()-1);


  if (str.length()>=2){

  return lastChar + middle + firstChar;

  }

  else {
  return str;
  }
}

此代码不起作用...如果字符串长度小于或等于 1,则使用 else 语句隐式返回 str。

public String frontBack(String str) {

  char firstChar = str.charAt (0);

  char lastChar = str.charAt (str.length()-1);

  String middle = str.substring(1, str.length()-1);


  if (str.length()>=2){

  return lastChar + middle + firstChar;

  }

  else {
  return str;
  }
}

你需要编程来防御


1.

对于一个字符串

  String middle = str.substring(1, str.length()-1);

这将是

str.substring(1, 0)

这是无效的


2.

对于空字符串( length = 0 ),您的代码将尝试查看index = -1无效,甚至 index = 0 无效


3.

如果strnull怎么办

你总是要考虑边界条件:

str 为空? str 为空("") str 是 1 个字符? 还请记住,Java 的子字符串在开始位置包含但在结尾不包含。

    public String frontBack(String str) {
      if (str == null || str.length()<2){
          //if str is null - return empty. else return the string itself
          return str == null ? "" : str;
      }else{
         //do the actual first last swap
         return  str.charAt(str.length()-1)+ str.substring(1,str.length()-1) + str.charAt(0);
      } 
    }

我重新编写了我的代码并将其缩小到一个简单的区别。 区别在于放置显式语句以说明等于或小于 1 的字符串。 这显然不能通过 catch-all else 语句隐式处理。 仍然不确定为什么?

它与隐式或显式无关。 问题只是在方法中执行行的顺序,即从上到下。

当它在“隐式”情况下到达您的 if/else 时,上面的三行,例如char firstChar = str.charAt(0); 已经发生(或已经失败)。 对于空字符串,它将立即在该行上出现 StringIndexOutOfBounds 异常(查看异常的行号),然后该方法将停止执行,因为它将异常抛出该方法。 (对此的技术术语是abrupt completion 。)如果抛出该异常,则下面的 if/else 将不会发生,因此它无法在事后追溯防止异常。 如果您将三个使用字符串的语句从方法顶部移动到 if/else 的“if”分支内部,则该代码将正常工作,以便在不需要时不会执行它们。

在“显式”情况下,您添加了if (str.length() <= 1) return str; 在方法的顶部,它可以阻止下面的行执行,因为return语句将在尝试使用字符串中不存在的字符之前退出方法。 如果它在方法中较低,那么该声明将无济于事。


我只想添加一些关于“null”的内容,因为此页面上的其他回答者抱怨您的代码无法抵御 null 参数。 考虑一下您的方法将如何处理特殊输入是很好的,但是在这里,您的代码已经正确地防御了 null 参数,因为当您尝试在 null 上调用charAtlengthsubstring时,它将抛出NullPointerException方法,因为它应该。

有时应该检查并允许空值,但在这里不应该。 如果在没有有效字符串的情况下调用, frontBack可能返回什么? 有些人可能会说它应该返回 null,有些人可能会说它应该返回空字符串,有些人可能会说它应该将它强制转换为一个字符串,从而返回"luln" 没有完全合理或明确正确的方法来处理它,适用于所有调用者。 因此, frontBack应该采取 null 不是可接受的输入的立场。 那么如果他们传入null,那是调用者的错,如果调用者传入垃圾,那么他们应该把垃圾扔回他们是正确的(当然,这是比喻;你实际上会抛出一个异常对象,而不是原始输入) 所以他们被迫妥善处理。 通过显式将垃圾强制为有效输入来容忍和为坏调用者找借口是错误的做法,因为它隐藏了错误并使程序的行为更加微妙。

如果该方法有副作用,例如修改数据结构、写入文件或调用具有副作用的其他方法,则 null 输入可能是危险的,因为该方法可能会在不使用str情况下完成一些副作用。 然后,尝试使用str会在某个时候抛出异常,使事情未完成并处于无效状态。 理想情况下,应该观察到副作用完全发生或根本不发生。 在这种情况下,最好检查 null 并在方法顶部自己抛出异常:

if (str == null) throw new NullPointerException();

这不会对这个简单的方法产生影响,因为它没有副作用(它纯粹是函数式的)并且因为它已经无条件地调用了str方法,这将导致无论如何抛出相同的异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM