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 тип.

Объявленный тип возврата метода должен быть супертипом фактического типа времени выполнения возвращаемого объекта. Вам повезло привести к правильному типу.

Другие вопросы по тегам