1

为什么下面的代码会产生一个不错的 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 起作用。

提前致谢。

4

4 回答 4

7

这是因为 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。

于 2013-07-08T08:28:56.567 回答
1

在 API 文档中StringBuilder.subSequence

调用表单的这个方法

sb.subSequence(begin, end)

行为方式与调用完全相同

sb.substring(begin, end)

虽然String是 a CharSequence,但String不是 a StringBuilder。所以选角失败了。

你可以这样做:

StringBuilder s12= new StringBuilder(s1);
s12.setLength(3);
于 2013-07-08T08:29:07.903 回答
1

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

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

sb.subSequence(begin, end) 的行为方式与调用完全相同

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

于 2013-07-08T08:30:56.817 回答
0

方法String.subSequence必须返回String简单实现CharSequence类型的运行时类型的对象。

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

于 2013-07-08T08:30:19.850 回答