Java语言怎么实现自动读取不同类型的变量并且切换不同类型的菜单?菜单和类型的变量的输入联动,这个怎么用代码去实现的呢
代码如下
import java.util.Scanner;
public class VariableMenu {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int menuOption;
do {
// 显示菜单选项
System.out.println("请选择变量类型:");
System.out.println("1. 整数");
System.out.println("2. 浮点数");
System.out.println("3. 字符串");
System.out.println("0. 退出");
// 读取用户选择的菜单选项
menuOption = scanner.nextInt();
// 根据用户选择的菜单选项执行相应的操作
switch (menuOption) {
case 1:
readIntVariable();
break;
case 2:
readFloatVariable();
break;
case 3:
readStringVariable();
break;
case 0:
System.out.println("程序已退出!");
break;
default:
System.out.println("无效的选择,请重新输入!");
break;
}
} while (menuOption != 0);
scanner.close();
}
// 读取整数类型的变量
public static void readIntVariable() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入整数变量:");
int intValue = scanner.nextInt();
System.out.println("您输入的整数是:" + intValue);
// 执行其他操作
scanner.nextLine(); // 清空输入缓冲区的换行符
}
// 读取浮点数类型的变量
public static void readFloatVariable() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入浮点数变量:");
float floatValue = scanner.nextFloat();
System.out.println("您输入的浮点数是:" + floatValue);
// 执行其他操作
scanner.nextLine(); // 清空输入缓冲区的换行符
}
// 读取字符串类型的变量
public static void readStringVariable() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入字符串变量:");
String stringValue = scanner.nextLine();
System.out.println("您输入的字符串是:" + stringValue);
// 执行其他操作
}
}
要实现自动读取不同类型的变量并切换不同类型的菜单,你可以使用Java的输入输出和条件语句来实现。下面是一个示例代码,演示了如何根据不同的变量类型展示不同的菜单,并根据用户选择进行相应的操作:
import java.util.Scanner;
public class MenuExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 显示菜单选项
System.out.println("请选择变量类型:");
System.out.println("1. 整数");
System.out.println("2. 浮点数");
System.out.println("3. 字符串");
// 获取用户选择
int choice = scanner.nextInt();
scanner.nextLine(); // 读取换行符
// 根据选择展示不同的操作菜单
switch (choice) {
case 1:
System.out.println("请输入整数变量:");
int intValue = scanner.nextInt();
scanner.nextLine(); // 读取换行符
// 在这里执行针对整数变量的操作
System.out.println("您输入的整数是:" + intValue);
break;
case 2:
System.out.println("请输入浮点数变量:");
double doubleValue = scanner.nextDouble();
scanner.nextLine(); // 读取换行符
// 在这里执行针对浮点数变量的操作
System.out.println("您输入的浮点数是:" + doubleValue);
break;
case 3:
System.out.println("请输入字符串变量:");
String stringValue = scanner.nextLine();
// 在这里执行针对字符串变量的操作
System.out.println("您输入的字符串是:" + stringValue);
break;
default:
System.out.println("无效的选择");
break;
}
scanner.close();
}
}
这段代码首先展示了一个选择菜单,用户可以选择不同的变量类型。根据用户的选择,程序会要求用户输入相应类型的变量。然后,根据变量类型执行相应的操作。
需要注意的是,这段代码只是一个简单示例,实际应用中你可能需要增加更多的错误处理和逻辑。希望这个示例能帮助到你!
不知道你这个问题是否已经解决, 如果还没有解决的话:我们创建一个类(Server)来表示服务器
首先在Server类中写一个方法 startServer() 来表示启动一个服务器
此时,我们发现一个可以优化的点:
在未来的使用中,有可能我们的端口号不是固定的,所以,我们将端口号单独的放在一个配置文件中server.properties,在启动服务器时,我们先读取一遍配置文件,在配置文件中找到需要的端口号,以后只需要改配置文件就可以了。
port=9999
接下来我们创建一个类ServerFileReader ,这个类中我们读取这个server.properties的配置文件,这个ServerFileReader类中运用了一个缓存机制,避免每一次获取端口号都需要读取一次配置文件,回降低性能,所以在每次类加载之前,用静态代码块先读取一次配置文件中的信息,将这些信息全部存到一个Map集合中,以后在每次需要获取端口号的时候,就不用再使用I/O去读取配置文件了,直接去访问这个Map集合就可以了。
public class ServerFileReader {
private static HashMap<String,String> map = new HashMap<>();
static {
try {
Properties prop = new Properties();
prop.load(new FileReader("src/server.properties"));
Enumeration en = prop.propertyNames();
while (en.hasMoreElements()){
String key = (String) en.nextElement();
String value = prop.getProperty(key);
map.put(key,value);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getValue(String key){
return map.get(key);
}
}
然后我们在每次启动服务器的时候获取端口号就调用这个getValue()方法,再通过Integer.parseInt()方法将这个端口号字符串转化成int类型
public void startServer(){
try {
System.out.println("========启动服务器========");
//获取端口号
int port = Integer.parseInt(ServerFileReader.getValue("port"));
//创建一个服务
ServerSocket serverSocket = new ServerSocket(port);
while(true){
//等待某一个客户端过来连接,如果连接到了就会产生一个socket对象
Socket socket = serverSocket.accept();
//启动一个线程,负责处理当前浏览器发送过来的消息
ServerHandler handler = new ServerHandler(socket);
handler.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
由于服务器和浏览器之间存在一种一对多的关系(多个浏览器可以同时访问一个服务器),这里为了避免第二个用户访问是资源被占用的问题,我们创建一个线程对象ServerHandler来处理多线程并发的问题。ServerHandler类首先继承Thread类变成一个线程对象。然后再重写run()方法。当然为了接收刚才在浏览器端传输过来的数据,我们需要一个Socket对象当做属性,再提供一个构造方法。在服务器端有一个方法会等待一个客户端过来连接,serverSocket.accept()方法会返回一个Socket对象,这个Socket对象就是刚才浏览器端发送请求的那个Socket对象了
public class ServerHandler extends Thread{
private Socket socket;
public ServerHandler(Socket socket) {
this.socket = socket;
}
public void run(){
}
}
在这个线程对象ServerHandler类中我们需要完成以下这几件事情。
private void receiveRequest(){
try {
InputStream is = socket.getInputStream();//最基本的字节流
InputStreamReader isr = new InputStreamReader(is);//将字节流转化成字符流
BufferedReader reader = new BufferedReader(isr);//将字符流包装成高级流,缓冲流,可以读取一行消息
String contentAndParams = reader.readLine();
//接受到浏览器发送过来的请求后,开始调用下一个方法(解析内容和参数)
this.parseContentAndParams(contentAndParams);
} catch (IOException e) {
e.printStackTrace();
}
}
private void parseContentAndParams(String contentAndParams){
//创建两个变量分别存储content和params
String content = null;
HashMap<String,String> paramsMap = null;
//按照?将contentAndParams拆开
//?前面的部分是content ?后面的部分是params
//按照问号将其拆分
String[] arr = contentAndParams.split("\\?");
if(arr.length == 2){
//如果有携带问号,content就是问号前面部分
//再将问号后面部分的每一个key=value处理好后存入paramsMap集合
content = arr[0];
String params = arr[1];
String[] keyAndValues = params.split("&");
paramsMap = new HashMap<>();
for (String keyAndValue : keyAndValues) {
String[] kv = keyAndValue.split("=");
paramsMap.put(kv[0],kv[1]);
}
}else{
//如果没有问号,那么整个部分都是content
content = arr[0];
}
//---------------至此,浏览器传输过来的信息已经解析完毕-------------
//创建两个对象,一个对象是包含所有请求信息的,另一个对象是为了接收响应回来的结果
//传递给你的是空对象,在控制层执行完毕后将这个对象填满
HttpServletRequest request = new HttpServletRequest(content,paramsMap);
HttpServletResponse response = new HttpServletResponse();
ServletController.findController(request,response);
//---------------程序执行到这里,证明response对象已经被填满了-----------
this.responseToBrowser(response);
}
注意:当服务器解析完成后得到了一个字符串content和一个paramsMap集合。我们需要通过这两个参数去找到具体的控制层去执行相应的事情,此时为了参数传递方便以及为了方便后续代码的维护,我们创建了一个HttpServletRequest对象去存储这个content和paramsMap
public class HttpServletRequest {
//创建一个类,用来储存浏览器发送过来的请求信息
private String content;
private HashMap<String,String> paramsMap;
public HttpServletRequest(String content, HashMap<String, String> paramsMap) {
this.content = content;
this.paramsMap = paramsMap;
}
public HttpServletRequest() {
}
/**
* 获取paramsMap集合中的值,根据具体哪一个键就可以取出与之对应的值了
* @param key 键
* @return 返回与该key对应的值
*/
public String getParameter(String key){
return this.paramsMap.get(key);
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public HashMap<String, String> getParamsMap() {
return paramsMap;
}
public void setParamsMap(HashMap<String, String> paramsMap) {
this.paramsMap = paramsMap;
}
}
当然,找到对应的控制层Controller之后,需要将他们执行完毕后的结果返回给ServerHandler对象,这里我们不用再findController()方法上设计返回值,我们直接在调用这个findController()方法的时候传递一个HttpServletResponse 对象,(注意:此时传递的HttpServletResponse 对象是一个空对象,没有任何东西,我们之所以可以利用这种方式来接收返回值的目的是因为HttpServletResponse 对象本身就是一个应用数据类型,我们可以在方法执行完毕后将这个对象填满,就可以接收到返回值了)
我们在这个HttpServletResponse类中提供了几个方法,可以调用这个write()方法将响应信息写出去。
//创建一个类,用来储存服务器响应回来的信息
public class HttpServletResponse {
//创建一个StringBuilder处理字符串
private StringBuilder responseContent = new StringBuilder();
public void write(String str){
this.responseContent.append(str);
}
public String getResponseContent(){
return this.responseContent.toString();
}
}
也可以通过读取一个文件的方式(可以将响应信息提前写到一个路径下的文件中去)然后通过I/O去读取这个文件,将这个文件中的信息每一行字符串写回去,这个文件目前我们暂时用index.view的方式描述,当然这个文件就是将来我们的jsp文件或者是html文件,这个文件中有可能携带有一些特殊含义的符号,当响应回浏览器后再在浏览器进行解析响应回去的字符串,然后展示,呈现在用户眼前。
public void sendRedirect(String filePath){
BufferedReader reader = null;
try {
File file = new File("src/file/"+filePath);
reader = new BufferedReader(new FileReader(file));
String value = reader.readLine();
while(value != null){
this.responseContent.append(value);
value = reader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
现在,我们已经写好了HttpServletRequest这个类和HttpServletResponse这个类,可以去调用findController()这个方法,由于findController()这个方法做的事情,与这个ServerHandler类中的方法做的事情有些不一致,我们将其抽离出去形成一个新的类ServletController,在ServerHandler类中写一个findController()方法去找寻与资源名对应的控制层(通过反射机制)
注意:(由于我们在浏览器端输入的URL地址串中的每一个符号都有特殊意义,点号代表所表示文件的后缀名,表示文件类型,所以我们在输入URL地址串的时候只能输入资源的名字和后缀名,还不能输入这个资源对应的Controller控制层具体在哪一个包下,但是,如果通过反射机制Class.forName()方法去加载类的时候是必须要传递一个类全名给他的,所以我们只能用过使用配置文件的方式将资源名与之对应的Controller的类全名写到配置文件中,这里我们定义了一个web.properties的配置文件)
index=controller.IndexController
login=controller.LoginController
然后我们有了这个配置文件,就可以每次通过资源名,参考配置文件中与资源名相对应的类全名去找到具体对应的Controller类,从而就可以通过反射机制,去加载找到该类了
但是此时出现了两个可以优化的点:
1、我们每次在执行findController方法的时候都会去读取一次配置文件,这样会大大降低程序的性能,所以我们在这个类中增加一个缓存机制,就是在每次类加载之前就将配置文件中的信息全部读取一个,存储到一个Map集合中,我们以后执行findController()方法的时候就可以不再需要读取配置文件了,直接在这个Map集合中去找,这样就可以优化一下性能的问题。
static{
try {
Properties prop = new Properties();
prop.load(new FileReader("src/web.properties"));
//将配置文件中的信息全部读取出来放入到controllerNameMap集合中
Enumeration en = prop.propertyNames();
while (en.hasMoreElements()){
String content = (String)en.nextElement();
String realControllerName = prop.getProperty(content);
controllerNameMap.put(content,realControllerName);
}
} catch (IOException e) {
e.printStackTrace();
}
}
2、我们发现Controller对象与之前我们写的Service和Dao的对象特别相似,里面只有方法在做事情,没有属性,所以我们可以考虑将每一个Controller对象设计成一个单例模式,就是每次在找到一个Controller对象的时候,我们就可以将这个对象存到Map集合中,下一次要使用这个Controller对象的时候,就可以直接在这个Map集合中去取就行了。
最后我们,整理优化一下findController()方法:
public static void findController(HttpServletRequest request,HttpServletResponse response){
//获取资源名
String content = request.getContent();
try {
//获取这个类的对象
HttpServlet controllerObject = controllerObjectMap.get(content);
//如果对象不存在,证明之前没有使用过这个类,那就再通过反射的方式
//参考配置文件(缓存)去创建一个该类的对象
if(controllerObject == null){
//参考配置文件(缓存),找到真实的类名
String realControllerName = controllerNameMap.get(content);
//判断请求的真实名字是否存在,如果请求的真实名字也不存在,就不处理了
if(realControllerName != null){
//如果存在就通过反射区找到这个类
Class clazz = Class.forName(realControllerName);
//创建一个该类的对象
controllerObject = (HttpServlet) clazz.newInstance();
//将新创建的类对象放入集合中,下一次使用就不用创建对象了
controllerObjectMap.put(content,controllerObject);
}else{
throw new ClassNotFoundException();
}
}
//-------------以上可以确保controllerObject对象肯定存在---------------
//通过反射获取这个类中的对应方法
Class controllerClass = controllerObject.getClass();
Method serviceMethod = controllerClass.getMethod("service", HttpServletRequest.class, HttpServletResponse.class);
//找到对应的方法后就执行这个方法
serviceMethod.invoke(controllerObject,request,response);
} catch (ClassNotFoundException e) {
response.write("请求的"+content+"Controller找不到");
} catch (NoSuchMethodException e) {
response.write("405 没有可以执行的方法");
} catch (Exception e) {
e.printStackTrace();
}
}
现在我们通过findController()方法找到了资源名对应的Controller控制层,所以我们就可以通过这个控制层去找到我们要响应给浏览器的内容。
此时我么通过控制层找到了要响应的内容,我们提前把这些内容写到了文件中。现在我们只需要读取文件,把文件中的内容字符串,这些字符串就是即将要写回浏览器的响应信息,我们把这些信息存到HttpServletResponse对象中,此时这个HttpServletResponse的内容不再为空了。
我们模拟了一个简单的html语句,表示控制层对应的响应信息
欢迎进入银行系统<br>
<form action="login" method="get">
请输入用户名<input name="username" value=""><br>
请输入密码<input name="password" value=""><br>
感谢使用,再见
我们单独设计一个方法,将刚才的HttpServletResponse对象传递给这个方法,我们将这里面的内容字符串(响应信息),响应给浏览器
private void responseToBrowser(HttpServletResponse response){
try {
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.println(response.getResponseContent());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
现在,我们通过输入了URL地址串,浏览器初步解析了这个URL地址串中的ip和端口号,通过ip和端口号创建了一个Socket对象,访问了服务器,服务器对这个资源名和参数做了进一步解析,得到了具体的资源名和参数,通过资源名找到了对应的控制层,从而找到了对应的响应信息,服务器也将响应信息写回浏览器了。我们现在回到浏览器这一端,将服务器响应给我们的信息做一个解析。
此时,由于我们模拟的响应信息是一个html标签的内容,所以我们根据html标签的规则对这些字符串进行进一步解析
要实现自动读取不同类型的变量并切换不同类型的菜单,您可以使用Java中的条件语句(如if-else语句或switch语句)来根据输入的变量类型来执行不同的操作。
首先,您需要定义一个变量来存储用户输入的值,例如:
String input = scanner.nextLine();
接下来,您可以使用if-else语句或switch语句来检查输入的值的类型,并根据类型执行不同的操作。例如:
使用if-else语句:
if (input.matches("\\d+")) {
// 执行数字类型操作
} else if (input.matches("[a-zA-Z]+")) {
// 执行字母类型操作
} else {
// 执行其他类型操作
}
使用switch语句:
switch (input) {
case "数字":
// 执行数字类型操作
break;
case "字母":
// 执行字母类型操作
break;
default:
// 执行其他类型操作
break;
}
在上述示例中,我们使用了正则表达式来检查输入的值是否为数字或字母。如果输入的值不是数字或字母,则视为其他类型。
在执行每种类型的操作后,您可以根据需要返回到菜单,让用户选择下一个操作。您可以使用循环语句(如while循环)来实现这个功能。
例如:
while (true) {
// 显示菜单
System.out.println("请选择操作:");
System.out.println("1. 数字操作");
System.out.println("2. 字母操作");
System.out.println("3. 其他操作");
// 获取用户选择
int choice = scanner.nextInt();
// 根据用户选择执行相应的操作
switch (choice) {
case 1:
// 执行数字类型操作
break;
case 2:
// 执行字母类型操作
break;
case 3:
// 执行其他类型操作
break;
default:
// 提示用户输入无效的选择
break;
}
}
在上述示例中,我们使用while循环来不断显示菜单并等待用户选择。根据用户选择,我们使用switch语句执行相应的操作。如果用户输入无效的选择,则提示用户重新输入。