ClassCastException с StringBuilder и CharSequence
Почему следующий код приведет к хорошему исключению ClassCastException:
public static void main(String []args){
StringBuilder s1 = new StringBuilder("quaqua");
StringBuilder s12= (StringBuilder)s1.subSequence(0,3);
System.out.println(s12);
}
тогда как следующий код (замена StringBuilder на String):
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 ответа
Это потому, что фактическим классом, который возвращает 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.
Поскольку 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
,
В API документы StringBuilder.subSequence
:
Вызов этого метода формы
sb.subSequence(begin, end)
ведет себя точно так же, как вызов
sb.substring(begin, end)
Хоть String
это CharSequence
, String
это не StringBuilder
, Таким образом, актерский состав не удался.
Вы можете сделать это вместо этого:
StringBuilder s12= new StringBuilder(s1);
s12.setLength(3);
Метод String.subSequence
должен был вернуть объект типа времени выполнения String
который просто реализует CharSequence
тип.
Объявленный тип возврата метода должен быть супертипом фактического типа времени выполнения возвращаемого объекта. Вам повезло привести к правильному типу.