【Java基础】018 -- 面向对象阶段项目下(拼图小游戏扩展)

news2024/11/18 8:33:47

文章目录

  • 切换游戏图片的业务分析:
    • 1,所需要的技术点
    • 2,分析业务逻辑
  • 项目实现步骤:
    • 添加组件
    • 绑定事件:
    • 代码实现
  • 登录界面的业务分析:
    • 1,所需要的技术点
    • 2,分析业务逻辑
  • 项目实现步骤:
    • 主界面设置:
    • 添加组件
    • 绑定事件:
    • 代码实现
      • LoginJFrame.java
      • User.java
      • CodeUtil.java

切换游戏图片的业务分析:

在这里插入图片描述

  • 分析业务逻辑
  • 分析所需要的技术点

1,所需要的技术点

在这个界面中,我们需要哪些技术点:

整个的菜单就是JMenuBar

功能,关于我们:JMenu

更换图片:JMenu

重新游戏,重新登录,关闭游戏,美女,动物,运动:JMenuItem

特点:如果在菜单中,还需要嵌套二级的菜单,那么可以用JMenu完成。JMenu里面是可以再次添加其他的JMenu的。

写代码的时候如何实现:

第一步:创建JMenuBar对象
第二步:创建三个JMenu对象(功能,关于我们,更换图片)
第三步:创建六个JMenuItem对象(重新游戏,重新登录,关闭游戏,美女,动物,运动)
第四步:把美女,动物,运动放到更换图片当中
第五步:把更换图片,重新游戏,重新登录,关闭游戏放到功能当中
第六步:把功能,关于我们放到JMenuBar
第七步:把JMenuBar放到整个界面当中

2,分析业务逻辑

1,给美女,动物,运动添加单击事件(动作监听)

2,当我们点击了美女之后,就会从13组美女图片中随机选择一组。

3,当我们点击了动物之后,就会从8组动物图片中随机选择一组。

4,当我们点击了运动之后,就会从10组运动图片中随机选择一组。

5,细节1:选择完毕之后,游戏界面中需要加载所有的小图片并且打乱顺序

6,细节2:按A的时候显示的是选择之后的图片
在这里插入图片描述

项目实现步骤:

  • 搭建菜单
  • 对美女,动物,运动添加点击事件

添加组件

//创建菜单并添加到界面当中
//1.创建菜单JMenuBar的对象
JMenuBar jMenuBar = new JMenuBar();
//2.创建菜单上面的两个选项JMenu
JMenu functionJMenu = new JMenu("功能");
JMenu aboutJMenu = new JMenu("关于我们");

//创建更换图片
JMenu changeImage = new JMenu("更换图片");

//3.创建JMenuItem的对象
JMenuItem girl = new JMenuItem("美女");
JMenuItem animal = new JMenuItem("动物");
JMenuItem sport = new JMenuItem("运动");
JMenuItem repalyItem = new JMenuItem("重新游戏");
JMenuItem reLoginItem = new JMenuItem("重新登录");
JMenuItem closeItem = new JMenuItem("关闭游戏");
JMenuItem accountItem = new JMenuItem("公众号");



//4.把美女,动物,运动添加到更换图片当中
changeImage.add(girl);
changeImage.add(animal);
changeImage.add(sport);

//5.把更换图片,重新游戏,重新登录,关闭游戏添加到功能当中
functionJMenu.add(changeImage);
functionJMenu.add(repalyItem);
functionJMenu.add(reLoginItem);
functionJMenu.add(closeItem);
//6.把公众号添加到关于我们当中
aboutJMenu.add(accountItem);

//5.把功能,关于我们添加到JMenuBar当中
jMenuBar.add(functionJMenu);
jMenuBar.add(aboutJMenu);

//6.把整个菜单JMenuBar添加到整个界面当中
this.setJMenuBar(jMenuBar);

绑定事件:

girl.addActionListener(this);
animal.addActionListener(this);
sport.addActionListener(this);


要在重写的方法中进行判断
if(点击是否为美女){
	随机选择图片
	修改PATH变量记录的值
	写一些重开一把的逻辑
}else if(点击是否为动物){
	随机选择图片
	修改PATH变量记录的值
	写一些重开一把的逻辑
}else if(点击是否为运动){
	随机选择图片
	修改PATH变量记录的值
	写一些重开一把的逻辑
}

代码实现

在这里插入图片描述

登录界面的业务分析:

  • 分析业务逻辑
  • 分析所需要的技术点

1,所需要的技术点

第一排:用户名文字其实是一张图片,还是用JLabel去管理ImageIcon

​ 输入框:JTextField(明文显示的输入框)

第二排:密码文字其实是一张图片,还是用JLabel去管理ImageIcon

​ 输入框:JPasswordField(密文显示的输入框)

第三排:验证码文字其实是一张图片,还是用JLabel去管理ImageIcon

​ 输入框:JTextField(明文显示的输入框)

​ 验证码wyS7i:用JLabel去管理文字,需要自己写一个生成验证码的工具类。

第四排:两个都是按钮,绿色跟红色是按钮的背景图

​ 当点击按钮不松的时候,按钮变灰,其实就是换一个深色的背景图。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W1TibaNn-1676118789954)(.\img\解释.png)]

2,分析业务逻辑

1,界面搭建。代码不需要大家写,大家主要完成里面的业务逻辑即可。界面搭建的代码在作业当中已经给出。

2,用静态代码块准备一些初始的用户信息

3,点击登陆按钮之后的逻辑:

  • 按下登陆不松,切换登陆按钮的背景图片
  • 松开登陆按钮,逻辑较为复杂
    • 获取用户输入的用户名,密码,验证码。
    • 先比较验证码(正确 错误)
    • 判断用户名和密码是否为空,只要有一个为空就不行
      • 细节:如果用户没有输入用户名和密码,在代码中获取的不是null,而是长度为0的字符串
    • 用户名,密码比较正确,显示登陆成功跳转游戏界面
    • 用户名,密码比较错误,提示错误

4,点击注册按钮之后的逻辑

  • 暂时不需要写逻辑,后面学习完IO的时候再补

5,点击验证之后

  • 更换一个新的验证码(写一个工具类提供验证码)

项目实现步骤:

  • 对主界面进行设置
  • 在主界面添加用户名和密码以及登录,注册按钮
  • 对登录按钮绑定鼠标事件

主界面设置:

设置大小
设置居中
设置置顶
设置关闭模式
取消内部布局
让界面可见

添加组件

创建JLabel添加用户名文字
对用户名文字设置位置和宽高:116, 135, 51, 19
    
创建用户名的文本输入框:JTextField
对用户名的文本输入框设置位置和宽高:195, 134, 200, 30
    
创建JLabel添加密码文字
对密码文字设置位置和宽高:130, 195, 35, 18
    
创建密码的文本输入框:JTextField
对密码的文本输入框设置位置和宽高:195, 195, 200, 30
    
创建登录的按钮:JButton
利用setIcon方法给登录按钮设置背景色
对登录的按钮设置位置和宽高:133, 260, 90, 40
    
创建注册的按钮:JButton
利用setIcon方法给注册按钮设置背景色
对登录的按钮设置位置和宽高:256, 260, 90, 40
    
创建背景色:JLabel
给背景色设置位置和宽高:0, 0, 470, 390
    
将上面7个组件添加到主界面的中心面板中

绑定事件:

给登录按钮绑定鼠标事件
当按下不松的时候:利用setIcon方法,修改登录按钮的背景色为蓝色
当松开的时候:利用setIcon方法,将按钮的背景色修改为红色
当点击的时候:校验用户输入的用户名和密码是否正确。

mouseClicked方法详解:

先判断当前按下的是否为登录按钮。
如果是登录按钮,获取输入框中的用户名和密码
判断1:是否为空,如果为空,提示:用户名和密码为空
判断2:判断用户名和密码是否为zhangsan,123456,如果正确隐藏登录界面,进入游戏界面。
判断3:判断用户吗和密码,如果错误,就展示弹框,提示:用户名和密码错误

展示弹框步骤:

成员位置创建JDialog对象

利用isVisible方法判断弹框是否存在,如果不存在则进行下面操作:
设置弹框的宽和高:100,100
设置弹框居中    
设置弹框置顶
移除弹框中所有文本
创建一个JLabel去编写文本内容
把文本JLabel添加到弹框当中
把弹框展示出来

代码实现

LoginJFrame.java

package com.thomas.ui;

import com.thomas.domain.User;
import com.thomas.ui.GameJFrame;
import com.thomas.util.CodeUtil;

import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;

public class LoginJFrame extends JFrame implements MouseListener {

    static ArrayList<User> allUsers = new ArrayList<>();
    static {
        allUsers.add(new User("zhangsan","123"));
        allUsers.add(new User("lisi","1234"));
    }


    JButton login = new JButton();
    JButton register = new JButton();

    JTextField username = new JTextField();
    //JTextField password = new JTextField();
    JPasswordField password = new JPasswordField();
    JTextField code = new JTextField();

    //正确的验证码
    JLabel rightCode = new JLabel();


    public LoginJFrame() {
        //初始化界面
        initJFrame();

        //在这个界面中添加内容
        initView();


        //让当前界面显示出来
        this.setVisible(true);
    }

    public void initView() {
        //1. 添加用户名文字
        JLabel usernameText = new JLabel(new ImageIcon("image\\login\\用户名.png"));
        usernameText.setBounds(116, 135, 47, 17);
        this.getContentPane().add(usernameText);

        //2.添加用户名输入框

        username.setBounds(195, 134, 200, 30);
        this.getContentPane().add(username);

        //3.添加密码文字
        JLabel passwordText = new JLabel(new ImageIcon("image\\login\\密码.png"));
        passwordText.setBounds(130, 195, 32, 16);
        this.getContentPane().add(passwordText);

        //4.密码输入框
        password.setBounds(195, 195, 200, 30);
        this.getContentPane().add(password);


        //验证码提示
        JLabel codeText = new JLabel(new ImageIcon("image\\login\\验证码.png"));
        codeText.setBounds(133, 256, 50, 30);
        this.getContentPane().add(codeText);

        //验证码的输入框
        code.setBounds(195, 256, 100, 30);
        this.getContentPane().add(code);


        String codeStr = CodeUtil.getCode();
        //设置内容
        rightCode.setText(codeStr);
        //绑定鼠标事件
        rightCode.addMouseListener(this);
        //位置和宽高
        rightCode.setBounds(300, 256, 50, 30);
        //添加到界面
        this.getContentPane().add(rightCode);

        //5.添加登录按钮
        login.setBounds(123, 310, 128, 47);
        login.setIcon(new ImageIcon("image\\login\\登录按钮.png"));
        //去除按钮的边框
        login.setBorderPainted(false);
        //去除按钮的背景
        login.setContentAreaFilled(false);
        //给登录按钮绑定鼠标事件
        login.addMouseListener(this);
        this.getContentPane().add(login);

        //6.添加注册按钮
        register.setBounds(256, 310, 128, 47);
        register.setIcon(new ImageIcon("image\\login\\注册按钮.png"));
        //去除按钮的边框
        register.setBorderPainted(false);
        //去除按钮的背景
        register.setContentAreaFilled(false);
        //给注册按钮绑定鼠标事件
        register.addMouseListener(this);
        this.getContentPane().add(register);


        //7.添加背景图片
        JLabel background = new JLabel(new ImageIcon("image\\login\\background.png"));
        background.setBounds(0, 0, 470, 390);
        this.getContentPane().add(background);

    }


    public void initJFrame() {
        this.setSize(488, 430);//设置宽高
        this.setTitle("拼图游戏 V1.0登录");//设置标题
        this.setDefaultCloseOperation(3);//设置关闭模式
        this.setLocationRelativeTo(null);//居中
        this.setAlwaysOnTop(true);//置顶
        this.setLayout(null);//取消内部默认布局
    }



    //点击
    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.getSource() == login) {
            System.out.println("点击了登录按钮");
            //获取两个文本输入框中的内容
            String usernameInput = username.getText();
            String passwordInput = password.getText();
            //获取用户输入的验证码
            String codeInput = code.getText();

            //创建一个User对象
            User userInfo = new User(usernameInput, passwordInput);
            System.out.println("用户输入的用户名为" + usernameInput);
            System.out.println("用户输入的密码为" + passwordInput);

            if (codeInput.length() == 0) {
                showJDialog("验证码不能为空");
            } else if (usernameInput.length() == 0 || passwordInput.length() == 0) {
                //校验用户名和密码是否为空
                System.out.println("用户名或者密码为空");

                //调用showJDialog方法并展示弹框
                showJDialog("用户名或者密码为空");


            } else if (!codeInput.equalsIgnoreCase(rightCode.getText())) {
                showJDialog("验证码输入错误");
            } else if (contains(userInfo)) {
                System.out.println("用户名和密码正确可以开始玩游戏了");
                //关闭当前登录界面
                this.setVisible(false);
                //打开游戏的主界面
                //需要把当前登录的用户名传递给游戏界面
                new GameJFrame();
            } else {
                System.out.println("用户名或密码错误");
                showJDialog("用户名或密码错误");
            }
        } else if (e.getSource() == register) {
            System.out.println("点击了注册按钮");
        } else if (e.getSource() == rightCode) {
            System.out.println("更换验证码");
            //获取一个新的验证码
            String code = CodeUtil.getCode();
            rightCode.setText(code);
        }
    }


    public void showJDialog(String content) {
        //创建一个弹框对象
        JDialog jDialog = new JDialog();
        //给弹框设置大小
        jDialog.setSize(200, 150);
        //让弹框置顶
        jDialog.setAlwaysOnTop(true);
        //让弹框居中
        jDialog.setLocationRelativeTo(null);
        //弹框不关闭永远无法操作下面的界面
        jDialog.setModal(true);

        //创建Jlabel对象管理文字并添加到弹框当中
        JLabel warning = new JLabel(content);
        warning.setBounds(0, 0, 200, 150);
        jDialog.getContentPane().add(warning);

        //让弹框展示出来
        jDialog.setVisible(true);
    }

    //按下不松
    @Override
    public void mousePressed(MouseEvent e) {
        if (e.getSource() == login) {
            login.setIcon(new ImageIcon("image\\login\\登录按下.png"));
        } else if (e.getSource() == register) {
            register.setIcon(new ImageIcon("image\\login\\注册按下.png"));
        }
    }


    //松开按钮
    @Override
    public void mouseReleased(MouseEvent e) {
        if (e.getSource() == login) {
            login.setIcon(new ImageIcon("image\\login\\登录按钮.png"));
        } else if (e.getSource() == register) {
            register.setIcon(new ImageIcon("image\\login\\注册按钮.png"));
        }
    }

    //鼠标划入
    @Override
    public void mouseEntered(MouseEvent e) {

    }

    //鼠标划出
    @Override
    public void mouseExited(MouseEvent e) {

    }

    //判断用户在集合中是否存在
    public boolean contains(User userInput){
        for (int i = 0; i < allUsers.size(); i++) {
            User rightUser = allUsers.get(i);
            if(userInput.getUsername().equals(rightUser.getUsername()) && userInput.getPassword().equals(rightUser.getPassword())){
                //有相同的代表存在,返回true,后面的不需要再比了
                return true;
            }
        }
        //循环结束之后还没有找到就表示不存在
        return false;
    }


}

User.java

package com.thomas.domain;

public class User {
    private String username;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

CodeUtil.java

package com.thomas.util;

import javax.print.attribute.standard.PresentationDirection;
import java.util.ArrayList;
import java.util.Random;

public class CodeUtil {

    public static String getCode() {
        // 创建大小字母列表 0~52
        ArrayList<Character> list = new ArrayList<>();
        // 向列表添加字母
        for (int i = 0; i < 26; i++) {
            list.add((char) ('a'+i));
            list.add((char) ('A'+i));
        }
        // 定义结果变量
        String result = "";
        Random r = new Random();
        // 拼接4个随机字母
        for (int i = 0; i < 4; i++) {
            int sIndex = r.nextInt(list.size());
            result += list.get(sIndex);
        }
        // 拼接数字
        int num = r.nextInt(10);
        result += num;

        // 让数字位随机
        char[] cArr = result.toCharArray();
        int cIndex = r.nextInt(5);
        char tmp = cArr[cIndex];
        cArr[cIndex] = cArr[4];
        cArr[4] = tmp;

        // 将字符数字重新变成字符串
        result = String.valueOf(cArr);

        return result;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/338661.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Day885.NextKeyLock加锁规则 -MySQL实战

NextKeyLock加锁规则 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于NextKeyLock加锁规则的内容。 加锁规则前提说明&#xff1a; MySQL 后面的版本可能会改变加锁策略&#xff0c;所以这个规则只限于截止到现在的最新版本&#xff0c;即 5.x 系列 <5.7.24&#…

搭建流媒体推流/拉流服务(RTMP/RTSP/HLS/HTTP-FLV)

一、什么是流媒体流媒体&#xff08;streaming media&#xff09;是指将一连串的媒体数据压缩后&#xff0c;经过网上分段发送数据&#xff0c;在网上即时传输影音以供观赏的一种技术与过程&#xff0c;此技术使得数据包得以像流水一样发送&#xff1b;如果不使用此技术&#x…

ffmpeg转码转封装小工具开发

如下图所示&#xff0c;是本人开发的一个转码转封装小工具 其中目标文件视频编码格式支持&#xff1a;H264&#xff0c;H265&#xff0c;VP8&#xff0c;VP9。 目标文件封装格式支持&#xff1a;mp4,mkv,avi,mov,flv。 目标文件音频编码格式支持两个&#xff0c;COPY和AAC&am…

安全寒假作业nginx反向代理+负载均衡上传webshell重难点+apache漏洞

1.应用场景 负载均衡作为现今解决web应用承载大流量访问问题的一种方案&#xff0c;在真实环境中得到广泛的部署。实现负载均衡的方式有很多种&#xff0c;比如 DNS 方式、HTTP 重定向方式、IP 负载均衡方式、反向代理方式等等。 比如基于dns的负载均衡&#xff1a; 当然还有…

LTD212次升级 | 官网社区支持PC端展示 • 官网新增证件查询应用,支持条形码扫码查询

1、新增证件查询应用&#xff0c;支持条形码扫码查询&#xff1b; 2、新增用户社区PC端功能&#xff1b; 01证件查询应用 1、新增证件查询应用功能 支持证件信息录入、打印功能&#xff0c;支持条形码扫码识别。 后台管理操作路径&#xff1a;官微中心 - 应用 - 证件查询 …

这才是CSDN最系统完整的网络安全学习路线(建议收藏)

01 什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防两面…

linux head命令(head指令)(获取文件或管道输出结果前n行,默认前10行)与sed命令区别

head命令是一个在Linux系统中常用的命令&#xff0c;用于读取文件的前几行&#xff08;默认读取前10行&#xff09; 文章目录使用方法读取文件的前10行&#xff1a;head filename读取文件的前n行&#xff1a;head -n行数 filename读取多个文件的前几行&#xff1a;head -n 行数…

六、Java框架之SpringBoot

黑马课程 文章目录1. SpringBoot入门1.1 SpringBoot入门案例步骤1&#xff1a;创建SpringBoot项目高版本springboot常见错误步骤2&#xff1a;创建BookController步骤3&#xff1a;启动服务器并运行程序pom.xml示例1.2 官网创建SpringBoot1.3 SpringBoot工程快速启动问题导入打…

网络安全实验室6.解密关

6.解密关 1.以管理员身份登录系统 url&#xff1a;http://lab1.xseclab.com/password1_dc178aa12e73cfc184676a4100e07dac/index.php 进入网站点击忘记密码的链接&#xff0c;进入到重置密码的模块 输入aaa&#xff0c;点击抓包&#xff0c;发送到重放模块go 查看返回的链接…

VScode 结合clangd 构建linux源代码阅读环境

1、背景介绍上一篇文章&#xff1a;VScode 结合Global构建linux源代码阅读环境 &#xff0c;介绍了在VS Code工具中通过remote-ssh远程登陆到Linux远程服务器&#xff0c;使用Global构建linux源代码阅读环境&#xff0c;对linux kernel代码进行解析&#xff0c;实现全局搜索、自…

Vue2创建移动端项目

一、Vscode Vscode 下载安装以及常用的插件 1、Vscode 下载 下载地址&#xff1a;Vscode 中文语言插件 搜索 chinese 主题 Atom 主题 文件图标主题 搜索 icon 源代码管理插件GitLens 搜索 GitLens Live Server _本地服务器 搜索 Live Server Prettier - Code formatt…

405 Method Not Allowed,CORS跨域,来也自动化OCR接口报错,Nginx处理OPTIONS请求

在使用来也的OCR接口时&#xff0c;请求报错了&#xff0c;提示CORS跨域。POST请求&#xff0c;请求url&#xff1a;http://mage.uibot.com.cn/v1/mage/ocr/bills&#xff0c;官方文档&#xff1a;请求与响应&#xff1a;预检请求OPTIONS正式请求错误信息看控制台和网络栏位内容…

【沁恒WCH CH32V307V-R1开发板输出DAC实验】

【沁恒WCH CH32V307V-R1开发板输出DAC实验】1. 前言2. 软件配置2.1 安装MounRiver Studio3. DAC项目测试3.1 打开DAC工程3.2 编译项目4. 下载验证4.1 接线4.2 演示效果5. 小结1. 前言 数字/模拟转换模块&#xff08;DAC&#xff09;&#xff0c;包含 2 个可配置 8/12 位数字输入…

自己动手做一个mini-chatgpt

开场最近chatgpt已经火爆了&#xff0c;几乎是家喻户晓老少皆知啊&#xff0c;公测推出60天后就已经是UV人数过亿&#xff0c;日访问量号称也是过亿。投资chatgpt研发团队的微软也是2个月内迅速推出自己的chatgpt的bing搜索&#xff0c;股票下载量都是暴增啊。前面文章已经介绍…

计算机网络自定向下 -- 浅谈可靠性之rdt协议

可靠性数据传输原理 可靠指数据在传输过程中不错&#xff0c;不丢&#xff0c;不乱 运输层要为应用层提供一种服务&#xff1a;数据可以通过一条可靠的信道进行传输&#xff0c;在该信道中传输的数据不会受到损坏或者丢失, 实现这种服务的是可靠数据传输协议。 要实现这种服…

python的opencv操作记录11——阈值分割

文章目录传统图像处理分割阈值分割一个应用场景opencv库中的阈值分割固定阈值THRESH_OTSU 大津法阈值自适应阈值传统图像处理分割 现在提到图像分割&#xff0c;很多人会直接想到当前火爆的深度学习的各种分割网络&#xff0c;比如实例分割&#xff0c;语义分割等。其实在传统…

Java爬虫Selenium+Java+ChromeDriver

一、爬虫工具 selenium 是一个模拟浏览器操作的工具&#xff0c;背后有google 维护源代码&#xff0c;支持全部主流浏览器&#xff0c;支持主流的编程语言&#xff0c;包括:java,Python,C#,PHP,Ruby,等&#xff0c;在本项目上使用的Java语言。 官网&#xff1a;https://www.sel…

【Vue】参数传递:如何同时传递 DTO 和 file 文件

日常开发时&#xff0c;如果遇到较为复杂的 DTO 对象的参数传递时&#xff0c;通常前端使用的请求头为&#xff1a;application/json&#xff08;JSON 格式的数据&#xff09;&#xff1b;而后端可以使用 RequestBody 接收一个 DTO 对象。但当需要在一个界面上同时传递 DTO 和附…

Java集合中的Map

MapMap接口键 值 对存储键不能重复&#xff0c;值可以重复Map三个实现类的存储结构HashMap&#xff1a;Hash表链表红黑树结构 线程不安全TreeMap&#xff1a; 底层红黑树实现HashTable&#xff1a;hash表链表红黑树 线程安全HashMapHashMap常用方法HashMap<String,String>…

[测开篇]设计测试用例的方法如何正确描述Bug

​ 文章目录为什么测试人员要写测试用例&#xff1f;怎样设计测试用例&#xff1f;&#xff08;总的方面&#xff09;1.基于需求设计测试用例&#xff08;总的方面&#xff09; 2.页面&#xff08;总的方面&#xff09; 3.非功能性测试&#xff08;具体方面&#xff09; 4.1 等…