为什么下面的代码会产生一个很好的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工作。
提前致谢。
答案 0 :(得分: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。
答案 1 :(得分:1)
在StringBuilder.subSequence
的API文档中:
调用
形式的此方法sb.subSequence(begin, end)
的行为方式与调用
完全相同sb.substring(begin, end)
虽然String
是CharSequence
,但String
不是StringBuilder
。所以演员阵容失败了。
您可以这样做:
StringBuilder s12= new StringBuilder(s1);
s12.setLength(3);
答案 2 :(得分:1)
因为subSequence()
方法在运行时返回String
对象而不是StringBuilder
对象。根据{{3}}
返回一个新的字符序列,它是该序列的子序列。 调用
形式的此方法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
。
答案 3 :(得分:0)
方法String.subSequence
必须返回运行时类型String
的对象,它只是实现CharSequence
类型。
声明的返回类型的方法必须是返回对象的实际运行时类型的超类型。您很幸运能够转换为正确的类型。