-3

No, not like this:

String stringName = "example";
String stringName2 = ("\"" + stringName + "\" secretly means \"i like trains\"");

The code I tried to use is:

long amountOfChars = chars.length;
int amountOfTimesLeft = 20;
String out = null;
Random random = new Random();
while (amountOfTimesLeft != 0) {
       long whichChar = (random.nextInt((int) (amountOfChars - 0 + 1)) + 0);
       StringBuilder sb = new StringBuilder(chars[(int) whichChar]);
       sb.append(out);
}

("chars" is an array of strings I've already defined)

What I expected it to do is: Get a random string from the chars array and add it to the out string, and repeat it 19 more times.

What it does:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 32 out of bounds for length 32
    at Main.main(Main.java:45)

I have really no idea what this means. Could someone help? (line 45 is the line that defines sb)

And yes, I know I forgot to decrease amountOfTimesLeft, but that's not the point of this question.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
elias
  • 1
  • 3
  • You CAN NOT append to an existing String, if you're talking about keeping the same reference. Java String is *immutable* and was specifically designed to NOT support that behavior. Whenever you append to a String, a new one will be created. If you try to 'hack' into the data of the String, you will probably cause memory leaks. What you can do instead is use a `StringBuilder` or a big enough `char[]` or anything else that is/supports a `CharSequence` but is modifiable. – JayC667 May 04 '22 at 08:41
  • What is `chars`? According your code there is no those variable. – Reporter May 04 '22 at 08:41
  • Now that you've updated your question: Simply keep the `StringBuilder` *outside* the loop, and it will do exactly as you wish. – JayC667 May 04 '22 at 08:42
  • `random.nextInt((int) (amountOfChars - 0 + 1)) + 0` why do you use those `+ 0`? By the way, there is your problem, you're generating numbers in a range that will exceed the length of `chars`. – Federico klez Culloca May 04 '22 at 08:43
  • 1
    By the way, you don't need to put the solution back in your question. It either belongs in an existing answer (in which case you should just [accept it](https://stackoverflow.com/help/accepted-answer)) or in a [self-answer](https://stackoverflow.com/help/self-answer) if the existing answers are not satisfying but you found a solution yourself. I'm reverting your latest edit to keep your question clean. – Federico klez Culloca May 04 '22 at 09:08
  • What do you think `new StringBuilder(chars[(int) whichChar])` does? And why do you do that? Similarly, what do you think `sb.append(out)` does, and why do you do it? – Mark Rotteveel May 04 '22 at 17:07
  • @MarkRotteveel `new StringBuilder(chars[(int) whichChar])` sets it to a random character from the array and i thought `sb.append(out)` would append to the actual out string but turns out im an idiot – elias May 18 '22 at 09:05
  • It doesn't, it calls `StringBuilder(int)`, which sets the initial length of the string builder. A `char` is essentially a 16-bit unsigned integer, and thus coercible to `int`. – Mark Rotteveel May 18 '22 at 09:33

2 Answers2

0

ArrayIndexOutOfBoundsException means that index for array chars is out of bounds.

That means that array chars has less than 32 available indexes (length of array is 32 or less). You can see in exception message: Index 32 out of bounds for length 32. Length of that array is 32, which means available indexes are from 0 to 31 inclusive. Java counts array indexes from 0.

However your usage of StringBuilder class is wrong. In that cycle you are creating new instance of StringBuilder every iteration StringBuilder sb = new StringBuilder(chars[(int) whichChar]); . Create StringBuilder instance once before cycle and then just use append method.

You are also always appending null to sb since out is always null.

Also make sure you manipulateamountOfTimesLeft, becuase this way the cycle will be infinite.

Example solution:

long amountOfChars = chars.length -1; //-1 to prevent ArrayIndexOutOfBoundsException
int amountOfTimesLeft = 20;
Random random = new Random();
StringBuilder sb = new StringBuilder();
while (amountOfTimesLeft != 0) {
       long whichChar = (random.nextInt((int) (amountOfChars - 0 + 1)) + 0);
       sb.append(chars[(int) whichChar]);
       amountOfTimesLeft--; //decrease amountOfTimesLeft by 1
}

To get the actual String you can do sb.toString();

Wortig
  • 963
  • 2
  • 11
  • 37
  • Yeah, i am aware java counts them from 0. so do i just remove one string or did i missunderstand? edit: nevermind – elias May 04 '22 at 08:43
  • @elias `whichChar` whatever it is obviously results in 32 after casting to int, which is out of bounds for your array. Make sure you do not provide index that is out of bounds. Also do not create StringBuilder instance in every iteration in that cycle (new keyword). – Wortig May 04 '22 at 08:46
  • But wait, that would keep whichChar the same, so it would just append the same string from the array each time? The software is for appending a random string from the array 20 times, but if i just define sb twice wont it use the same one over and over? – elias May 04 '22 at 08:47
  • You do not need to define sb twice. 1. Define it once before while cycle like this: `StringBuilder sb = new StringBuilder();`. I also noticed you are appending `null` (because out is always null) to the sb. 2. Then change `sb.append(out);` to `sb.append(chars[(int) whichChar]);`. 3. To prevent accidental ArrayIndexOutOfBoundsException you can change `long amountOfChars = chars.length;` to `long amountOfChars = chars.length - 1;` – Wortig May 04 '22 at 08:55
  • but what would it be appending to now? ohhhhh wait im an idiot sorry, i thought it appended to what you put in sb.append, sorry my brain does not exist – elias May 04 '22 at 08:59
  • @elias Do not worry. Check my example code in answer and let me know if it helps. – Wortig May 04 '22 at 09:02
0

I made a little change to your code.

To make int random in a range, we use random.nextInt(max - min) + min. Here max is the max array index, the min is the index 0.

I moved the StringBuilder out of the loop. Reduce the condition value to break out of the loop when the condition is met.

Please be aware of casting long to int, it can lead to an Overflow issue.

    char[] chars = {'a', 'b', 'c', 'd'};
    long amountOfChars = chars.length;
    int amountOfTimesLeft = 20;
    Random random = new Random();
    StringBuilder sb = new StringBuilder();
    while (amountOfTimesLeft != 0)
    {
        long whichChar = (random.nextInt((int)(amountOfChars - 0)) + 0);
        sb.append(chars[(int)whichChar]);
        amountOfTimesLeft--;
    }
    
    System.out.println(sb.toString());
HienNg
  • 51
  • 3