Java子字符串:'字符串索引超出范围'

时间:2009-06-04 22:53:19

标签: java substring indexoutofboundsexception

我猜我收到了这个错误,因为该字符串正在尝试子串null值。但".length() > 0"部分不会消除这个问题吗?

以下是Java代码段:

if (itemdescription.length() > 0) {
    pstmt2.setString(3, itemdescription.substring(0,38));
} 
else { 
    pstmt2.setString(3, "_");
} 

我收到了这个错误:

 java.lang.StringIndexOutOfBoundsException: String index out of range: 38
    at java.lang.String.substring(Unknown Source)
    at MASInsert2.itemimport(MASInsert2.java:192)
    at MASInsert2.processRequest(MASInsert2.java:125)
    at MASInsert2.doGet(MASInsert2.java:219)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:627)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
    at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:835)
    at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:640)
    at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1286)
    at java.lang.Thread.run(Unknown Source)

13 个答案:

答案 0 :(得分:32)

  

我猜我得到了这个错误   因为字符串正在尝试   substring一个Null值。但不会   “。length()> 0”部分消除   那个问题?

不,当itemdescription为null时调用itemdescription.length()不会生成StringIndexOutOfBoundsException,而是生成NullPointerException,因为您实际上是在尝试调用 null 上的方法。

正如其他人所指出的,StringIndexOutOfBoundsException表示itemdescription的长度不超过38个字符。您可能想要处理这两个条件(我假设您要截断):

final String value;
if (itemdescription == null || itemdescription.length() <= 0) {
    value = "_";
} else if (itemdescription.length() <= 38) {
    value = itemdescription;
} else { 
    value = itemdescription.substring(0, 38);
}
pstmt2.setString(3, value);

如果你做了很多事情,可能是实用功能的好地方......

答案 1 :(得分:23)

遗憾的是substring没有以处理短字符串的方式实现 - 就像在其他语言中一样蟒。

好的,我们无法改变这一点,每次使用substr时都必须考虑这个边缘情况,而不是if-else子句我会选择这个较短的变体:

myText.substring(0, Math.min(6, myText.length()))

答案 2 :(得分:9)

您确实需要检查字符串的长度是否大于或等于38。

答案 3 :(得分:6)

我会推荐apache commons lang。单行解决问题。

pstmt2.setString(3, StringUtils.defaultIfEmpty(
    StringUtils.subString(itemdescription,0, 38), "_")); 

答案 4 :(得分:5)

substring(0,38)表示字符串必须为38个字符或更长。如果不是,“字符串索引超出范围”。

答案 5 :(得分:5)

if (itemdescription != null && itemdescription.length() > 0) {
    pstmt2.setString(3, itemdescription.substring(0, Math.min(itemdescription.length(), 38))); 
} else { 
    pstmt2.setString(3, "_"); 
}

答案 6 :(得分:2)

我假设您的列长度为38个字符,因此您希望截断 itemdescription以适应数据库。像下面这样的效用函数应该做你想要的:

/**
 * Truncates s to fit within len. If s is null, null is returned.
 **/
public String truncate(String s, int len) { 
  if (s == null) return null;
  return s.substring(0, Math.min(len, s.length()));
}

然后你就这样称呼它:

String value = "_";
if (itemdescription != null && itemdescription.length() > 0) {
  value = truncate(itemdescription, 38);
}

pstmt2.setString(3, value);

答案 7 :(得分:2)

当您尝试从比字符串长的索引开始获取子字符串时,Java的substring方法失败。

一个简单的替代方法是使用Apache Commons StringUtils.substring

public static String substring(String str, int start)

Gets a substring from the specified String avoiding exceptions.

A negative start position can be used to start n characters from the end of the String.

A null String will return null. An empty ("") String will return "".

 StringUtils.substring(null, *)   = null
 StringUtils.substring("", *)     = ""
 StringUtils.substring("abc", 0)  = "abc"
 StringUtils.substring("abc", 2)  = "c"
 StringUtils.substring("abc", 4)  = ""
 StringUtils.substring("abc", -2) = "bc"
 StringUtils.substring("abc", -4) = "abc"

Parameters:
str - the String to get the substring from, may be null
start - the position to start from, negative means count back from the end of the String by this many characters

Returns:
substring from start position, null if null String input

注意,如果您出于某种原因无法使用Apache Commons lib,那么您可以grab the parts you need from the source

// Substring
//-----------------------------------------------------------------------
/**
 * <p>Gets a substring from the specified String avoiding exceptions.</p>
 *
 * <p>A negative start position can be used to start {@code n}
 * characters from the end of the String.</p>
 *
 * <p>A {@code null} String will return {@code null}.
 * An empty ("") String will return "".</p>
 *
 * <pre>
 * StringUtils.substring(null, *)   = null
 * StringUtils.substring("", *)     = ""
 * StringUtils.substring("abc", 0)  = "abc"
 * StringUtils.substring("abc", 2)  = "c"
 * StringUtils.substring("abc", 4)  = ""
 * StringUtils.substring("abc", -2) = "bc"
 * StringUtils.substring("abc", -4) = "abc"
 * </pre>
 *
 * @param str  the String to get the substring from, may be null
 * @param start  the position to start from, negative means
 *  count back from the end of the String by this many characters
 * @return substring from start position, {@code null} if null String input
 */
public static String substring(final String str, int start) {
    if (str == null) {
        return null;
    }

    // handle negatives, which means last n characters
    if (start < 0) {
        start = str.length() + start; // remember start is negative
    }

    if (start < 0) {
        start = 0;
    }
    if (start > str.length()) {
        return EMPTY;
    }

    return str.substring(start);
}

答案 8 :(得分:1)

itemdescription短于38个字符。这就是StringOutOfBoundsException被抛出的原因。

检查.length() > 0只需确保String有一些非空值,您需要做的是检查长度是否足够长。你可以尝试:

if(itemdescription.length() > 38)
  ...

答案 9 :(得分:0)

您必须检查字符串长度。您假设只要String不是substring(0,38)就可以null,但实际上您需要String长度至少为38个字符。

答案 10 :(得分:0)

在适当的时候,我使用 matches 而不是 substring

带有子字符串

if( myString.substring(1,17).equals("Someting I expect") ) {
    // Do stuff
}
// Does NOT work if myString is too short

具有匹配项(必须使用正则表达式):

if( myString.matches("Someting I expect.*") ) {
    // Do stuff
}
// This works with all strings

答案 11 :(得分:0)

任何人都应该遇到同样的问题。

执行以下操作: str.substring(...(trim());

希望它对某些人有帮助?

答案 12 :(得分:-1)

如果itemdescription短于38个字符

,则会得到此信息

您可以查看抛出的异常以及何时使用JAVA API 在你的情况下为String #substring(int,int):https://docs.oracle.com/javase/9/docs/api/java/lang/String.html#substring-int-int-

substring
public String substring(int beginIndex, int endIndex)
   . . .

Throws:
 IndexOutOfBoundsException
 if the beginIndex is negative,
 or endIndex is larger than the length of this String object, 
 or beginIndex is larger than endIndex.



(same applies to previous java versions as well)