Search code examples
javapassword-generator

Password Generator throws IndexOutOfBoundsException when password length is taken from scanner


So I have made a random password Generator as homework for my Uni class, However i do have an issue with code breaking and exiting with "java.lang.IndexOutOfBoundsException : Invalid array range: 0 to 0" message once it gets to first itteration of loop in method that should generate my password. This is an updated version of code that implements scanner as option for user tu input his/her desired password lenght from keyboard. In previos version when password length was hardcoded as a set number, it worked allright. If there is anny mistake in question format or maybe the code looks ugly or whatever, I do apoligize beforehand as my coding skills are at the very bottom in my current stage.

package com.company;
import java.util.*;

public class Main {

    static final String AllTheCharactersOnMyKeyBoard = "~!@#$%^&*()_+`1234567890-=QWERTYUIOP{}qwertyuiop[]ASDFGHJKL:|asdfghjkl;'|ZXCVBNM<>?zxcvbnm,./'";
    static int PasswordLength;
    static List<Character> ListOfCharsOnMyKBoard = convertsTheStringToCharacterList(AllTheCharactersOnMyKeyBoard);
    static char[] GeneratedCharacters= new char[PasswordLength];

    public static void main(String[] args) {
        Scanner PassLengthScanner=new Scanner(System.in);
        System.out.println("How many Symbols You wish the new password to contain?");
        PasswordLength= PassLengthScanner.nextInt();
        GeneratedPassword();
        System.out.println(ListOfCharsOnMyKBoard);
        System.out.println("\n\n\nYour Password is:");
        System.out.println(GeneratedCharacters);
    }
    public static List<Character> convertsTheStringToCharacterList(String AllTheCharactersOnMyKeyBoard){
        List<Character> MyKeyBoardCharacterList= new ArrayList<>();
        for (char CHARACTER : AllTheCharactersOnMyKeyBoard.toCharArray()){
            MyKeyBoardCharacterList.add(CHARACTER);
        }
        return MyKeyBoardCharacterList;
    }
    public static void GeneratedPassword(){
        Random TheGenerator= new Random();
        for (int i=0; i<PasswordLength; i++) {
            char RandomOne = ListOfCharsOnMyKBoard.get(TheGenerator.nextInt(ListOfCharsOnMyKBoard.size()));
            GeneratedCharacters[i]=(RandomOne);
        }
    }
}

The stacktrace is:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
    at com.company.Main.GeneratedPassword(Main.java:31)
    at com.company.Main.main(Main.java:15)

Line 31 of the program is this line:

        GeneratedCharacters[i]=(RandomOne);

Solution

  • static int PasswordLength;
    

    This declares a variable and initializes it to 0. The latter part is a quite confusing trait of Java, I wish they had avoided it.

    static char[] GeneratedCharacters= new char[PasswordLength];
    

    This declares an array variable and initializes it to an array of length — wait, what is the value of PasswordLength? Right, 0, so an array of length 0, an array with no elements in it.

        PasswordLength= PassLengthScanner.nextInt();
    

    This reads a number from the keyboard and stores it in PasswordLength. However, it doesn’t change the array. The array still has length 0.

            GeneratedCharacters[i]=(RandomOne);
    

    This tries to store a value into an array element. The first time through your loop i is 0, so it should store into the element at index 0, which should most often be fine. Only since your array is empty, it fails with the exception and stack trace that you saw (I hope you saw the stacktrace).

    The solution is to allocate the array with new inside the main method and only after you have read the length into PasswordLength.

    Bonus info: Don’t use this for real passwords. Everyone can see here on Stack Overflow how you generated them, and new Random() gives predictable random numbers when we can guess approximately when you ran your program. If you want to use the program for real passwords, initialize TheGenerator like this:

        Random TheGenerator= SecureRandom.getInstance("SHA1PRNG");
    

    Short version of explanation: A SecureRandom gives unpredictable pseudorandom numbers, so is safe for generating real passwords.