【问题标题】:Java substring: 'string index out of range'Java 子字符串:'字符串索引超出范围'
【发布时间】:2010-10-31 12:16:36
【问题描述】:

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

这里是 Java sn-p:

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)

【问题讨论】:

    标签: java substring indexoutofboundsexception


    【解决方案1】:

    很遗憾,substring 没有以处理短字符串的方式实现——就像在其他语言中一样,例如蟒蛇。

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

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

    【讨论】:

    • 是的,这太荒谬了。
    【解决方案2】:

    我猜我收到了这个错误 因为字符串试图 子串一个 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);
    

    如果你经常这样做,可能是一个实用功能的好地方......

    【讨论】:

      【解决方案3】:

      我会推荐apache commons lang。单线可以解决问题。

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:
            if (itemdescription != null && itemdescription.length() > 0) {
                pstmt2.setString(3, itemdescription.substring(0, Math.min(itemdescription.length(), 38))); 
            } else { 
                pstmt2.setString(3, "_"); 
            }
            

            【讨论】:

            • 我真的很想知道 itemdescription.substring(0, itemdescription.length()) 会返回什么:)
            • var itemdescription = new String("Hello, World!");警报(itemdescription.substring(0,itemdescription.length));返回“你好,世界!”。
            • 他可能想用它做某事
            • 嗯,是的,那里应该有一个上限。这是给你的午夜帖子......
            【解决方案7】:

            当您尝试获取从比字符串长的索引开始的子字符串时,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】:

              我假设您的列长度为 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);
              

              【讨论】:

                【解决方案9】:

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

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

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

                【讨论】:

                  【解决方案10】:

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

                  【讨论】:

                    【解决方案11】:

                    如果合适,我会使用 ma​​tches 而不是 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
                    

                    【讨论】:

                    • 在大多数情况下,将字符串与== 进行比较是行不通的。模式匹配与字符串比较完全不同,在这种情况下,这是一个坏主意,特别是(但不仅)出于性能原因。
                    • 你说得对,亚历山大;更改为等于。我发现 Regex 非常方便且易于使用,但它的性能较低也是正确的。
                    【解决方案12】:

                    如果有人面临同样的问题。

                    这样做: str.substring (...(trim()) ;

                    希望对大家有所帮助?

                    【讨论】:

                      【解决方案13】:

                      如果 itemdescription 少于 38 个字符,您会得到这个

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

                      子字符串
                      公共字符串子字符串(int beginIndex,int endIndex)
                         . . .
                      
                      投掷:
                       IndexOutOfBoundsException
                       如果 beginIndex 为负数,
                       或 endIndex 大于此 String 对象的长度,
                       或 beginIndex 大于 endIndex。
                      
                      
                      
                      (同样适用于以前的 java 版本)
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2010-12-06
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2015-04-01
                        • 2012-01-15
                        • 2014-06-12
                        相关资源
                        最近更新 更多