Adding chars to a string

import java.util.Random;

public class PasswordRandomizer {
    // Define the variables
    private Random random = new Random();
    private int passwordLength;
    private String password = "";

    public PasswordRandomizer(int length) {
        // Initialize the variable
        this.passwordLength = length;
    }

    public String createPassword() {
        // write code that returns a randomized password
        for(int i = 0; i < this.passwordLength; i++){
            int j = random.nextInt();
            char symbol = "abcdefghijklmnopqrstuvwxyz".charAt(j);
            this.password = this.password + symbol; 
        }
        return this.password;
    }
}

How can I add chars to a string, I tried this but I get this error:

"Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -414383904".

Jon Skeet
people
quotationmark

This is the problem:

int j = random.nextInt();
char symbol = "abcdefghijklmnopqrstuvwxyz".charAt(j);

The charAt method requires that its argument is within the bounds of the string - you're just using a random integer from Random.nextInt() which could have any int value:

Returns the next pseudorandom, uniformly distributed int value from this random number generator's sequence. The general contract of nextInt is that one int value is pseudorandomly generated and returned. All 232 possible int values are produced with (approximately) equal probability.

You should use something like:

private static String final ALPHABET = "abcdefghijklmnopqrstuvwxyz";
...   
int j = random.nextInt(ALPHABET.length());
char symbol = ALPHABET.charAt(j);

That way you know that j will be within the bounds of the string (i.e. 0 <= j < ALPHABET.length()).

There are other things I'd change about your code though:

  • There's no need to use string concatenation here
  • There's no need to use an instance variable for Random (currently each password you generate will be longer than the previous one)
  • I'd use final fields
  • I'd use SecureRandom instead of Random for password generation
  • I'd make the class final
  • I'd allow the alphabet of characters to be passed in

So:

public final class PasswordRandomizer {
    private static final String DEFAULT_ALPHABET = "abcdefghijklmnopqrstuvwxyz";
    private final Random random = new SecureRandom();
    private final String alphabet;
    private final int passwordLength;

    public PasswordRandomizer(int length) {
        this(length, DEFAULT_ALPHABET);
    }

    public PasswordRandomizer(int length, String alphabet) {
        // TODO: Arguvment validation
        this.passwordLength = length;
        this.alphabet = alphabet;
    }

    public String createPassword() {
        char[] chars = new char[passwordLength];

        for (int i = 0; i < this.passwordLength; i++){
            chars[i] = alphabet.charAt(random.nextInt(alphabet.length());
        }
        return new String(chars);
    }
}

people

See more on this question at Stackoverflow