【问题标题】:ClassCastException with StringBuilder and CharSequence带有 StringBuilder 和 CharSequence 的 ClassCastException
【发布时间】:2013-07-08 08:25:26
【问题描述】:

为什么下面的代码会产生一个不错的 ClassCastException:

public static void main(String []args){
        StringBuilder s1 = new StringBuilder("quaqua");
        StringBuilder s12= (StringBuilder)s1.subSequence(0,3);
        System.out.println(s12);
     }

而下面的代码(用 String 代替 StringBuilder):

public static void main(String []args){
        String s1 = new String("quaqua");
        String s12= (String)s1.subSequence(0,3);
        System.out.println(s12);
     }

工作正常吗?;

我知道有 substring(int begin, int end); 方法,但我只是好奇为什么使用 StringBuilder(它实现 CharSequence)的演员表不起作用而使用 String 起作用。

提前致谢。

【问题讨论】:

    标签: java string stringbuilder charsequence


    【解决方案1】:

    这是因为 StringBuilder.subSequence 返回的实际类是 String:

    ...
    public CharSequence subSequence(int start, int end) {
        return substring(start, end);
    }
    
    public String substring(int start, int end) {
        ...
        return new String(value, start, end - start);
    }
    

    您不能将 String 转换为 StringBuilder。

    【讨论】:

      【解决方案2】:

      StringBuilder.subSequence 的 API 文档中:

      表单的这个方法的调用

      sb.subSequence(begin, end)
      

      行为方式与调用完全相同

      sb.substring(begin, end)
      

      虽然StringCharSequence,但String 不是StringBuilder。所以演员表失败了。

      您可以这样做:

      StringBuilder s12= new StringBuilder(s1);
      s12.setLength(3);
      

      【讨论】:

        【解决方案3】:

        因为subSequence() 方法在运行时返回String 对象,而不是StringBuilder 对象。根据StringBuilder#subSequence()的文档

        返回一个新的字符序列,它是该序列的子序列。 表单的这个方法的调用

        sb.subSequence(开始,结束) 行为方式与调用完全相同

        sb.substring(开始,结束)

        如果您在此处查看代码:

        public CharSequence subSequence(int beginIndex, int endIndex) {
            return this.substring(beginIndex, endIndex);
        }
        

        如果您看到substring() 的代码:

        public String substring(int beginIndex, int endIndex) {
            if (beginIndex < 0) {
                throw new StringIndexOutOfBoundsException(beginIndex);
            }
            if (endIndex > value.length) {
                throw new StringIndexOutOfBoundsException(endIndex);
            }
            int subLen = endIndex - beginIndex;
            if (subLen < 0) {
                throw new StringIndexOutOfBoundsException(subLen);
            }
            return ((beginIndex == 0) && (endIndex == value.length)) ? this
                    : new String(value, beginIndex, subLen);
        }
        

        它返回一个String,因为String实现了CharSequence接口,subSequence()的返回类型可以是CharSequence的返回类型,但在内部它与String一起工作。而你不能String 转换为StringBuilder

        【讨论】:

          【解决方案4】:

          方法String.subSequence 必须返回运行时类型为String 的对象,它只是实现CharSequence 类型。

          声明的方法返回类型必须是返回对象的实际运行时类型的超类型你很幸运能转换为正确的类型。

          【讨论】:

            猜你喜欢
            • 2017-12-10
            • 1970-01-01
            • 2011-04-05
            • 1970-01-01
            • 2013-12-19
            • 2016-04-12
            • 2014-05-14
            • 2019-09-18
            • 2012-04-25
            相关资源
            最近更新 更多