0

0

Java中实现动态编号列表与用户选择的教程

花韻仙語

花韻仙語

发布时间:2025-11-16 18:44:11

|

162人浏览过

|

来源于php中文网

原创

Java中实现动态编号列表与用户选择的教程

本教程旨在解决在java中创建动态编号列表并处理用户选择时常见的逻辑错误,特别是关于列表编号的重复累加和选择判断的准确性问题。通过分析一个密码管理器场景中的具体案例,我们将详细讲解如何正确初始化计数器、生成有序列表、以及如何基于用户输入准确地访问对应的数据,从而避免索引越界和逻辑判断失误。

1. 理解问题背景与目标

在开发交互式应用程序时,我们经常需要向用户展示一个编号列表,并允许用户通过输入数字来选择列表中的某个项。一个典型的应用场景是密码管理器,它需要列出所有存储的网站,并根据用户的选择显示对应的用户名和密码。

我们的目标是实现以下功能:

  1. 从数据源(如websites.getwebList())获取网站列表。
  2. 为每个网站生成一个从1开始递增的编号,并以“编号 - 网站地址”的格式显示。
  3. 接收用户的数字输入,作为其选择的网站编号。
  4. 根据用户选择的编号,从对应的数据源(如usernames.getuserNameList()和passList.getPassList())中检索并显示相关的用户名和密码。

2. 分析原始代码中的常见问题

原始代码在实现上述目标时,遇到了两个主要问题:

  1. 列表编号的持续累加(“指数级增长”):websiteNum变量在每次循环显示列表时没有被重置,导致列表编号不断增加。
  2. 选择逻辑的错误判断:用户选择后,用于判断的条件if (userNum == websiteNum)总是失败,因为websiteNum在此时已经变成了列表的最后一个编号,而非用户选择的特定项的编号。

让我们逐一分析:

立即学习Java免费学习笔记(深入)”;

2.1 问题一:列表编号的累加错误

在原始代码中,websiteNum变量在while (yesNo == 'n')循环外部被初始化(或在某个地方被初始化一次),然后在for循环内部每次迭代时递增。

// ...
// FIXME website num is exponentially increasing everytime no is entered.
            for (i = 0; i < (websites.getwebList().size()); i++) {
                System.out.print(websiteNum + " - ");
                System.out.println(websites.getwebList().get(i));
                websiteNum = websiteNum + 1; // 每次显示后递增
            }
// ...

当外层while循环再次执行时(例如,用户选择不添加密码并再次显示列表),websiteNum的值并没有被重置回1。它会从上次循环结束时的值继续递增,从而产生“2 - website1.com 4 - website2.com”这类错误的编号。

解决方案:每次需要显示列表时,都应该将用于编号的计数器重新初始化为1。

凡人网络购物系统jsp版(JspShop)
凡人网络购物系统jsp版(JspShop)

基于jsp+javabean+access(mysql)三层结构的动态购物网站,v1.2包含v1.0中未公开的数据库连接 的java源文件 一,网站前台功能: 产品二级分类展示:一级分类--二级分类--产品列表--详细介绍(名称,图片,市场价,会员价,是否推荐,功能介绍等) 产品搜索:关键字模糊搜索 定购产品:选择商品--确认定购--填写收货人信息--选择付款方式--订单号自动生成(限登录用户)

下载

2.2 问题二:选择逻辑的错误判断

原始代码中,在用户输入选择后,尝试通过以下逻辑来访问数据:

// ...
            while (alwaysTrue == true) // 此循环是多余的,且条件恒为真
            {
// FIXME always results in cannot access
                if (userNum == websiteNum) // 这里的 websiteNum 是列表显示后的最终值
                {
                    System.out.println(websites.getwebList().get(j));
                    System.out.println(usernames.getuserNameList().get(j));
                    System.out.println(passwords.getPassList().get(j));
                    break;
                }
                else
                {
                    System.out.println("Cannot access, try again.");
                    break;
                }
            }
// ...

这里的websiteNum在if条件被检查时,其值是上一个for循环结束后,列表的最后一个编号加1。例如,如果列表有2项,websiteNum最终会是3。因此,除非用户恰好输入3(这通常不是一个有效选择),userNum == websiteNum这个条件几乎总是false,导致程序总是输出“Cannot access, try again.”。

此外,while (alwaysTrue == true)是一个冗余且可能导致无限循环的结构(尽管内部的break语句阻止了无限循环)。正确的做法是直接使用if-else结构进行判断。

解决方案:用户输入的userNum代表的是列表中的序号(从1开始)。要将其转换为列表或数组的索引(从0开始),需要进行userNum - 1的转换。然后,应该检查这个转换后的索引是否在有效范围内,而不是将其与websiteNum的最终值进行比较。

3. 修正后的实现策略

结合上述分析,我们提出以下修正策略:

  1. 初始化列表计数器:在每次显示列表之前,声明并初始化一个局部变量作为列表编号计数器,例如int websiteNum = 1;。
  2. 生成编号列表:使用for循环遍历网站列表,同时递增websiteNum来显示当前项的编号。
  3. 获取用户输入:使用Scanner获取用户输入的数字。
  4. 转换并验证索引:将用户输入的编号减1,得到对应的零基索引。在访问列表元素之前,务必检查此索引是否在有效范围内(0
  5. 访问数据:如果索引有效,则使用该索引从所有相关列表中获取并显示数据。

4. 示例代码:修正后的密码管理器列表选择功能

下面是基于上述策略修正后的代码示例:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 模拟数据源类
class WebsiteData {
    private List<String> webList;
    private List<String> userNameList;
    private List<String> passList;

    public WebsiteData() {
        webList = new ArrayList<>();
        userNameList = new ArrayList<>();
        passList = new ArrayList<>();

        webList.add("website1.com");
        userNameList.add("user1");
        passList.add("pass123");

        webList.add("website2.org");
        userNameList.add("user2");
        passList.add("securePass");

        webList.add("example.net");
        userNameList.add("admin");
        passList.add("mySecret");
    }

    public List<String> getwebList() {
        return webList;
    }

    public List<String> getuserNameList() {
        return userNameList;
    }

    public List<String> getPassList() {
        return passList;
    }
}

public class PasswordManagerTutorial {

    public static void main(String[] args) {
        Scanner scnr = new Scanner(System.in);
        WebsiteData websites = new WebsiteData(); // 模拟网站数据

        // 假设这里是外层循环的开始,例如用户选择“不添加密码”
        char yesNo = 'n'; // 模拟用户输入 'n'

        while (yesNo == 'n') {
            System.out.println("\n--- 现有网站列表 ---");
            int websiteNumCounter = 1; // 每次显示列表前重置计数器
            for (int i = 0; i < websites.getwebList().size(); i++) {
                System.out.println(websiteNumCounter + " - " + websites.getwebList().get(i));
                websiteNumCounter++;
            }

            System.out.println("请输入您想访问的网站编号 (输入0退出):");
            int userNum = scnr.nextInt();

            if (userNum == 0) {
                System.out.println("退出选择模式。");
                break; // 退出外层 while 循环
            }

            // 将用户输入的编号转换为零基索引
            int selectedIndex = userNum - 1;

            // 验证用户输入的索引是否有效
            if (selectedIndex >= 0 && selectedIndex < websites.getwebList().size()) {
                System.out.println("\n--- 网站信息 ---");
                System.out.println("网站: " + websites.getwebList().get(selectedIndex));
                System.out.println("用户名: " + websites.getuserNameList().get(selectedIndex));
                System.out.println("密码: " + websites.getPassList().get(selectedIndex));
                // 假设显示完信息后,用户可以再次选择或退出
                System.out.println("\n是否继续选择网站?(y/n)");
                yesNo = scnr.next().charAt(0);
                if (yesNo == 'y') {
                    yesNo = 'n'; // 保持在选择循环中
                } else {
                    break; // 退出外层循环
                }
            } else {
                System.out.println("无效的编号,请重试。");
                // 保持 yesNo 为 'n',以便重新显示列表并允许用户再次选择
            }
        }

        scnr.close();
        System.out.println("程序结束。");
    }
}

代码运行示例:

--- 现有网站列表 ---
1 - website1.com
2 - website2.org
3 - example.net
请输入您想访问的网站编号 (输入0退出):
2

--- 网站信息 ---
网站: website2.org
用户名: user2
密码: securePass

是否继续选择网站?(y/n)
y

--- 现有网站列表 ---
1 - website1.com
2 - website2.org
3 - example.net
请输入您想访问的网站编号 (输入0退出):
5
无效的编号,请重试。

--- 现有网站列表 ---
1 - website1.com
2 - website2.org
3 - example.net
请输入您想访问的网站编号 (输入0退出):
1

--- 网站信息 ---
网站: website1.com
用户名: user1
密码: pass123

是否继续选择网站?(y/n)
n
程序结束。

5. 注意事项与最佳实践

  1. 变量作用域与初始化:理解局部变量的作用域至关重要。像websiteNumCounter这样的计数器,如果每次显示列表都需要从1开始,就应该在每次显示列表的循环(或方法)内部声明并初始化。
  2. “差一”错误(Off-by-one Error):用户通常从1开始计数,而数组或列表的索引是从0开始。在处理用户输入时,务必进行userNum - 1的转换。
  3. 输入验证:始终对用户输入进行验证。检查转换后的索引是否在有效范围内(0
  4. 避免冗余循环:原始代码中的while (alwaysTrue == true)是多余的。如果只需要一次判断和执行,直接使用if-else结构即可。
  5. 清晰的提示信息:向用户提供清晰的指令(如“输入0退出”)和反馈(如“无效的编号,请重试”),能大大提升用户体验。
  6. 代码结构与可读性:使用有意义的变量名(如websiteNumCounter代替websiteNum,以区分其作为计数器的作用),合理的缩进和注释,可以提高代码的可读性和可维护性。

6. 总结

本教程通过一个具体的密码管理器案例,详细讲解了在Java中实现动态编号列表和用户选择时可能遇到的常见问题及其解决方案。核心在于正确地管理列表编号计数器的生命周期(每次显示前重置),以及将用户输入转换为有效的零基索引并进行严格的边界检查。掌握这些基本原则,将有助于您编写出更加健壮、用户友好的交互式应用程序。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

846

2023.08.22

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

106

2023.09.25

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

492

2023.10.18

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

382

2023.10.25

java中break的作用
java中break的作用

本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。

120

2025.10.15

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

261

2025.10.24

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1010

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

611

2024.08.29

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.3万人学习

C# 教程
C# 教程

共94课时 | 11.2万人学习

Java 教程
Java 教程

共578课时 | 80.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号