Question

Why the following code will yield a nice ClassCastException:

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

whereas the following code ( substituting StringBuilder with String):

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

works fine?;

I understand that there is the method substring(int begin, int end); however I am just curious why the cast with StringBuilder (which implements CharSequence) does not work whereas with String works.

Thanks in advance.

Was it helpful?

Solution

This is because the actual class that StringBuilder.subSequence returns is 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);
}

You cannot cast String to StringBuilder.

OTHER TIPS

In API docs of StringBuilder.subSequence:

An invocation of this method of the form

sb.subSequence(begin, end)

behaves in exactly the same way as the invocation

sb.substring(begin, end)

Though String is a CharSequence, String is not a StringBuilder. So the cast failed.

You can do this instead:

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

Because the subSequence() methods returns a String object at runtime and not a StringBuilder object. As per the documentation of StringBuilder#subSequence()

Returns a new character sequence that is a subsequence of this sequence. An invocation of this method of the form

sb.subSequence(begin, end) behaves in exactly the same way as the invocation

sb.substring(begin, end)

If you go through the code here :

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

And if you see the code for 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);
}

It returns a String , since String implements CharSequence interface the return type of subSequence() can be that of CharSequence , but the internally it works with String. And you cannot cast String to StringBuilder.

Method String.subSequence must have returned object of runtime type String which simply implements CharSequence type.

Declared return type of method must be super type of actual runtime type of returned object. You are lucky to cast to a correct type.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top