5

I got a StringIndexOutOfBoundsException for setCharAt(int index, char ch):

StringBuilder word = new StringBuilder(4); for(int i = 0; i < 4; i++) word.setCharAt(i,'-'); 

StringBuilder(int capacity): Constructs a string builder with no characters in it and an initial capacity specified by the capacity argument.

setCharAt(int index, char ch): The character at the specified index is set to ch.

The only thing I can think of is that no memory was allocated, but then what's the point of StringBuilder(int capacity)?

1
  • 1
    Here's some discussion of the purpose of the capacity argument/constructor. Commented Jun 8, 2013 at 1:08

3 Answers 3

6

Just use StringBuilder.append()

The constructor you're using does nothing to put data in the StringBuilder.

It only specifies a practical size for the StringBuilder (which I believe is for performance).

Until you actually put stuff in the StringBuilder, your code will throw Exceptions.

Note that the documentation you've quoted says this explicitly:

"Constructs a string builder with NO CHARACTERS in it..."

Sign up to request clarification or add additional context in comments.

2 Comments

That's actually what I ended up doing. I was just wondering what the constructor actually does, if not allocate any memory? I understand that no characters are in, but why does there need to be any?
I suggest reading the source code to find out. I believe that the capacity is primarily used internally for performance (as the StringBuilder grows), but I'm not sure.
5

The only thing I can think of is that no memory was allocated, but then what's the point of StringBuilder(int capacity)?

The point is to provide an up front opportunity to allocate a sufficiently large chunk of memory to handle all the data that will be inserted. When the capacity is exceeded, internally a new chunk of memory will have to be allocated and all the values from the old memory copied over. As you can imagine, this could be a performance burden if it occurs a multitude of times.

The behavior is not really odd or unexpected, in fact it is quite consistent with the practice of encapsulation.

What would ArrayList do? An ArrayList is backed by an array, and using a sufficient initial capacity is more performant, however doing so still does not allow arbitrary access to indices of the array.

I think the odd behavior is thinking of a StringBuilder as a representation of a char[]. The representation is properly encapsulated at it is, don't poke at it in curious ways.

Comments

4

This seems like a bit of an odd behavior in StringBuilder.

In AbstractStringBuilder (which it inherits), the constructor is defined as:

AbstractStringBuilder(int capacity) { value = new char[capacity]; } 

However, when using setCharAt(), we check count instead:

public void setCharAt(int index, char ch) { if ((index < 0) || (index >= count)) throw new StringIndexOutOfBoundsException(index); value[index] = ch; } 

So, since we didn't set count by using the initial constructor, we have an error thrown in our faces.

count is redefined in append(), replace(), insert(), and setLength(). You could solve your problem by also calling setLength(4); however, as @jahroy pointed out, it is simpler to just use append().

Relevant source codes: StringBuilder, AbstractStringBuilder

10 Comments

I've never looked at the source, but I assumed it looked something like that, which is why I was so confused when I got the exception.
@SteveP. Yeah... Technically, it should let you. But instead of checking value.length, it checks count which wasn't updated. It's hard to actually say if this is by design or not.
@TimBender (I know. :P) I would say, though, that if I manually set a capacity, it should allow me to manipulate that data how I see fit. In the case of the default constructor, it allocates 16 blocks in array, but I should not be able to access them. In terms of the explicit setting of the capacity, though, I think that's different. (Being forced to call setLength() isn't so bad though, I guess.)
Maybe they should just change the name of the argument from capacity to growFactor (or something more appropriate)... It's funny how important names can be.
@jahroy I agree completely.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.