Подстрока Java: 'string index out of range'

Я предполагаю, что я получаю эту ошибку, потому что строка пытается подстроку 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)

11 ответов


Я предполагаю, что я получаю эту ошибку потому что строка пытается подстрока значение Null. Но не этот." длина() > 0" части устранения этот вопрос?

нет, вызывая itemdescription.length () когда itemdescription равен null, не будет генерировать 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);

может быть хорошим местом для служебной функции, если вы делаете это много...


жаль, что substring не реализован таким образом, чтобы обрабатывать короткие строки, как на других языках, например Python.

хорошо, мы не можем изменить это и должны учитывать этот крайний случай каждый раз, когда мы используем substr, вместо предложений if-else я бы пошел на этот более короткий вариант:

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

вам действительно нужно проверить, является ли длина строки больше или равна 38.


Я бы порекомендовал Apache commons lang. Один лайнер решает проблему.

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

substring(0,38) означает, что строка должна быть 38 или более символов. Если нет, "строковый индекс находится вне диапазона".


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

Я предполагаю, что ваш столбец имеет длину 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);

itemdescription короче 38 символов. Вот почему StringOutOfBoundsException выбрасывается.

проверка .length() > 0 просто убеждается String имеет некоторое значение NOT-null, что вам нужно сделать, это проверить, что длина достаточно длинная. Вы можете попробовать:

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

в 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

вы должны проверить длину строки. Вы предполагаете, что вы можете сделать substring(0,38) пока строка не null, но на самом деле вам нужна строка длиной не менее 38 символов.


вы получаете это, если itemdescription короче 38 символов

вы можете посмотреть, какие исключения выбрасываются и когда в API JAVA в вашем случае для строки#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)