我正在尝试自学Java,而且我最近一直在使用内置编译器进行在线练习。我的代码适用于大多数条件,除了两个字符串长度小于2的条件。
此特定练习题的网址为: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;
}
}
答案 0 :(得分:2)
您需要 计划来保护
<强> 1 强>
表示一个字符串
String middle = str.substring(1, str.length()-1);
这将是
str.substring(1, 0)
无效
<强> 2 强>
对于空字符串(length
= 0),您的代码将尝试查看无效的index = -1
,甚至索引= 0无效
第3 强>
如果str
为null
答案 1 :(得分:0)
你总是要考虑边界条件:
str是否为空? str是空的(&#34;&#34;)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);
}
}
答案 2 :(得分:0)
我已经重新设计了我的代码并将其缩小到一个简单的区别。这种差异是放置 显式 语句来计算等于或小于1的字符串。显然无法通过catch-all else语句处理 隐式 。还是不确定为什么?
它与隐式或显式无关。问题只是在方法中执行行的顺序,从上到下。
当它在“隐式”情况下到达你的if / else时,上面的三行,例如char firstChar = str.charAt(0);
已经发生(或已经失败)。对于一个空字符串,它将立即在该行上显示一个StringIndexOutOfBounds异常(查看异常的行号),然后该方法将停止执行,因为它将异常抛出该方法。 (此技术术语是abrupt completion。)如果抛出该异常,则不会发生下面的if / else,因此它不能追溯性地阻止异常。如果将三个字符串使用语句从方法顶部移动到内部 if / else的“if”分支,那么该代码将正常工作,以便在不需要时不执行它们。
在“显式”情况下,您在方法的 top 处添加了if (str.length() <= 1) return str;
,可以防止下面的行执行,因为return
语句将会在尝试使用字符串中不存在的字符之前退出方法。如果方法中的含量较低,那么该声明就无济于事。
我只想添加一些关于'null'的内容,因为此页面上的其他回答者都抱怨你的代码没有防御null参数。考虑你的方法如何处理特殊输入是很好的,但是在这里,你的代码已经正确地防御了null参数,因为当你试图调用charAt
或length
或{{1}时在null上,它将从方法中抛出substring
。
有时候应该检查并允许null,但是在这里它不应该。如果在没有有效字符串的情况下调用,那么NullPointerException
可能会返回什么?有些人可能会说它应该返回null,有些人可能会说它应该返回空字符串,有些人可能会说它应该将它强制转换为字符串然后返回frontBack
。没有完全明智或毫不含糊的正确方法来处理它对所有呼叫者都有效。因此,"luln"
应采取null不是可接受的输入的立场。然后它是调用者的错误如果他们传入null,并且如果调用者传入垃圾,那么他们应该将垃圾扔回他们是正确的(当然,比喻;你实际上会抛出一个异常对象,而不是原始输入)所以他们被迫正确处理它。通过明确地将垃圾强制转换为有效输入来容忍和为不良调用者找借口是不对的,因为它隐藏了错误并且使程序的行为更加微妙。
如果方法具有side effects,例如修改数据结构,写入文件或调用其他具有副作用的方法,那么空输入可能是危险的,因为该方法可能会完成一些副作用不使用frontBack
。然后,尝试使用str
会在某个时刻抛出异常,使事情半完成并处于无效状态。理想情况下,应观察到副作用是完全发生还是根本不发生。在这种情况下,最好检查null并在方法的顶部自己抛出异常:
str
这不会对这个简单的方法产生影响,因为它没有副作用(它是purely functional),并且因为它已经无条件地调用if (str == null) throw new NullPointerException();
上的方法,这将导致相同的异常无论如何都会被抛出。