Java密码生成器如何无需大量if语句实现字符类型自定义功能
实现方案
你可以通过动态拼接可用字符集的方式避免冗余if判断,也可以选择支持「选中的字符类型必须至少出现一次」的合规性要求,具体实现如下:
基础版(最简实现,无冗余判断)
仅需要对原核心方法做参数改造,动态拼接用户选中的字符集合作为字典即可:
// 核心生成方法改造 public static String generatePassword(int len, boolean useUppercase, boolean useLowercase, boolean useDigits, boolean useSpecialChars) { StringBuilder dicBuilder = new StringBuilder(); // 按用户选择拼接可用字符集 if (useUppercase) dicBuilder.append(ALPHA_CAPS); if (useLowercase) dicBuilder.append(ALPHA); if (useDigits) dicBuilder.append(NUMERIC); if (useSpecialChars) dicBuilder.append(SPECIAL_CHARS); // 合法性校验:至少选中一类字符 if (dicBuilder.isEmpty()) { throw new IllegalArgumentException("至少需要选择一种字符类型"); } String dic = dicBuilder.toString(); // 优化生成逻辑,用StringBuilder提升拼接性能 StringBuilder result = new StringBuilder(len); for (int i = 0; i < len; i++) { int index = random.nextInt(dic.length()); result.append(dic.charAt(index)); } return result.toString(); }
触发方法适配改造,传入UI层的用户选择布尔值即可:
public void generatePasswordAgain(ActionEvent event) throws IOException { // 以下四个布尔值替换为实际从UI组件(如复选框)获取的用户选择状态即可 boolean useUpper = upperCaseCheckBox.isSelected(); boolean useLower = lowerCaseCheckBox.isSelected(); boolean useNum = numericCheckBox.isSelected(); boolean useSpecial = specialCheckBox.isSelected(); genPassword.setText(generatePassword(length, useUpper, useLower, useNum, useSpecial)); }
进阶版(零零散if,支持每类选中字符至少出现一次)
如果希望完全去掉零散的if判断,同时保证生成的密码一定覆盖所有用户选中的字符类型,可使用如下实现:
// Java 16+ 可直接使用record定义字符池配对结构,低版本可替换为AbstractMap.SimpleEntry<String, Boolean> record CharPool(String chars, boolean enabled) {} public static String generatePassword(int len, boolean useUppercase, boolean useLowercase, boolean useDigits, boolean useSpecialChars) { List<CharPool> enabledPools = new ArrayList<>(); List<CharPool> allPools = List.of( new CharPool(ALPHA_CAPS, useUppercase), new CharPool(ALPHA, useLowercase), new CharPool(NUMERIC, useDigits), new CharPool(SPECIAL_CHARS, useSpecialChars) ); // 循环筛选可用字符池,无零散if for (CharPool pool : allPools) { if (pool.enabled()) { enabledPools.add(pool); } } // 合法性校验 if (enabledPools.isEmpty()) { throw new IllegalArgumentException("至少需要选择一种字符类型"); } if (len < enabledPools.size()) { throw new IllegalArgumentException("密码长度至少需要为" + enabledPools.size() + "位,以覆盖所有选中的字符类型"); } StringBuilder result = new StringBuilder(len); // 先为每类选中的字符池各取1个字符,保证至少出现一次 for (CharPool pool : enabledPools) { String chars = pool.chars(); result.append(chars.charAt(random.nextInt(chars.length()))); } // 剩余长度从所有可用字符中随机选取 String allDic = enabledPools.stream().map(CharPool::chars).collect(Collectors.joining()); int remainLen = len - enabledPools.size(); for (int i = 0; i < remainLen; i++) { result.append(allDic.charAt(random.nextInt(allDic.length()))); } // 打乱字符顺序,避免前几位固定为不同类型的字符 char[] resultArr = result.toString().toCharArray(); for (int i = resultArr.length - 1; i > 0; i--) { int j = random.nextInt(i + 1); char temp = resultArr[i]; resultArr[i] = resultArr[j]; resultArr[j] = temp; } return new String(resultArr); }
触发方法的改造逻辑和基础版完全一致。
内容的提问来源于stack exchange,提问作者Jackwannsee
相关产品推荐
相关产品推荐

