Checking letter case (Upper/Lower) within a string in Java

Although this code is likely beyond the understanding of a novice, it can be done in one line using a regex with positive and negative look-aheads:

boolean ok = 
    password.matches("^(?=.*[A-Z])(?=.*[!@#$%^&*])(?=.*\\d)(?!.*(AND|NOT)).*[a-z].*");

A loop like this one:

else if (!(Character.isLowerCase(ch)))
            {
                for (int i=1; i<password.length(); i++)
                {
                   ch = password.charAt(i);

                    if (!Character.isLowerCase(ch))
                       {  
                        System.out.println("Invalid password - Must have a Lower Case character.");
                        password = "";
                       }
                     // end if
                } //end for
            }

Has an obvious logical flaw: You enter it if the first character is not lowercase, then test if the second character is not lower case. At that point you throw an error.

Instead, you should do something like this (not full code, just an example):

boolean hasLower = false, hasUpper = false, hasNumber = false, hasSpecial = false; // etc - all the rules
for ( ii = 0; ii < password.length(); ii++ ) {
  ch = password.charAt(ii);
  // check each rule in turn, with code like this:
  if Character.isLowerCase(ch) hasLower = true;
  if Character.isUpperCase(ch) hasUpper = true;
  // ... etc for all the tests you want to do
}

if(hasLower && hasUpper && ...) {
  // password is good
} 
else {
  // password is bad
}

Of course the code snippet you provided, besides the faulty logic, did not have code to test for the other conditions that your "help" option printed out. As was pointed out in one of the other answers, you could consider using regular expressions to help you speed up the process of finding each of these things. For example,

hasNumber  : use regex pattern "\d+" for "find at least one digit"
hasSpecial : use regex pattern "[!@#$%^&*]+" for "find at least one of these characters"

In code:

hasNumber  = password.matches(".*\\d.*");  // "a digit with anything before or after"
hasSpecial = password.matches(".*[!@#$%^&*].*");
hasNoNOT   = !password.matches(".*NOT.*");
hasNoAND   = !password.matches(".*AND.*");

It is possible to combine these things in clever ways - but especially when you are a novice regex user, it is much better to be a little bit "slow and tedious", and get code that works first time (plus you will be able to figure out what you did six months from now).


To determine if a String contains an upper case and a lower case char, you can use the following:

boolean hasUppercase = !password.equals(password.toLowerCase());
boolean hasLowercase = !password.equals(password.toUpperCase());

This allows you to check:

if(!hasUppercase)System.out.println("Must have an uppercase Character");
if(!hasLowercase)System.out.println("Must have a lowercase Character");

Essentially, this works by checking if the String is equal to its entirely lowercase, or uppercase equivalent. If this is not true, then there must be at least one character that is uppercase or lowercase.

As for your other conditions, these can be satisfied in a similar way:

boolean isAtLeast8   = password.length() >= 8;//Checks for at least 8 characters
boolean hasSpecial   = !password.matches("[A-Za-z0-9 ]*");//Checks at least one char is not alpha numeric
boolean noConditions = !(password.contains("AND") || password.contains("NOT"));//Check that it doesn't contain AND or NOT

With suitable error messages as above.

Tags:

Java