I want to validate my password with eight characters or more and must contain at least two non-alphabetic (i.e., not A-Z) characters
You may use
s.matches("(?=(?:[^a-zA-Z]*[a-zA-Z]){2}).{8,}")
See the regex demo.
Another way of writing the same
s.matches("(?=.{8})(?:[^a-zA-Z]*[a-zA-Z]){2}.*")
Explanation
^ - (not necessary in .matches as the method requires a full string match) - start of string
(?= - start of a positive lookahead that requires, immediately to the right of the current location,
(?:[^a-zA-Z]*[a-zA-Z]){2} - a non-capturing group that matches 2 consecutive occurrences of:
[^a-zA-Z]* - any 0+ chars other than ASCII letters
[a-zA-Z] - an ASCII letter
) - end of the lookahead
.{8,} - any 8 or more chars other than line break chars, as many as possible
$ - (not necessary in .matches as the method requires a full string match) - end of string
In (?=.{8})(?:[^a-zA-Z]*[a-zA-Z]){2}.* pattern, the first lookahead requires at least 8 chars, then at least two letters are requires using the (?:[^a-zA-Z]*[a-zA-Z]){2} pattern, and then .* matches the rest of the string.