实践篇-Java命令参数解析

Java命令与用法

`Java`命令一般有以下2种形式:

//java [-options] class [args]
//java [-options] -jar jarfile [args]


我们的 `java` 命令需要携带三组参数:分别是选项主类名(或者JAR文件名)。选项是由`-`开头的,比如我们熟悉的  `-version`(输出产品版本并退出),当然被括起来证明是可选的,如果选用非选项参数,那你就得给出全的主类名,如果你选择`-jar`选项那接着就得跟`jar`文件名,然后就可以从这个文件中寻找主类了。


这里提到了主类,什么是主类呢?我们知道所有的java程序运行,都有一个main方法,这个方法也被称为我们程序的入口点,public static void main(String[] args) ,那该方法所在的类我们就叫主类


那什么是选项呢?选项就是java给我们提供的一个功能项,使用的时候用 [-options]表示,那java都给我们提供了哪些功能项呢?有很多。


选项

用途

 -server

选择 "server" VM

 默认 VM 是 server.

 -cp 

<目录和 zip/jar 文件的类搜索路径>

-classpath 

<目录和 zip/jar 文件的类搜索路径>

                 用 ; 分隔的目录, JAR 档案

                 和 ZIP 档案列表, 用于搜索类文件。

-verbose

[class|gc|jni]

启用详细输出

 -? -help 

 输出此帮助消息

-Xms<size> 设置初始堆空间大小
-Xmx<size> 设置最大堆空间大小
-Xss<size> 设置线程栈空间大小

java命令与实现

那作为一个菜鸡,我肯定是不可能全实现的,所以我挑了一些比较容易的进行实现:

1.  `java -version` 输出产品版本并退出

1.  `java -help -?` 输出此帮助消息

1.  `java -cp your/classpath yourClassName arg1 ...`<目录和 zip/jar 文件的类搜索路径>

1.  `java -classpath your/classpath yourClassName arg1 arg2 ...`<目录和 zip/jar 文件的类搜索路径>用 ; 分隔的目录, JAR 档案 和 ZIP 档案列表, 用于搜索类文件。


实现思路

1. 把java命令看成一串字符,那我们就可以用String类型的字符进行接收

2. 然后把命令切割成字符数组,用于命令参数解析,给不同的解析结果给不同的标识

3. 将解析结果的标识取出,根据标识进行相应结果的返回

4. 结束并退出程序


代码实现

首先定义一个命令类,用于命令校验和标识,之后提供一些属性值,代码如下:

private Boolean versionFlag = false; //版本命令标记
private Boolean helpFlag = false;      //帮助命令标记
private Boolean isRightFormat = true; //校验命令格式是否正确
private Boolean isRightOpt = true; //校验命令格式是否正确
private String clazz;   //要编译的java文件
private String[] args; //执行Java文件所需的参数
private String cpOption;  //classPath 的路径; java -cp(-classpath) xxx
/*使用 -Xjre 的选项:这是一个非标准的选项,java命令中是没有的,使用这个选项目的是用来指定启动类路径来寻找和加载Java标准库中的类
   即JAVA_HOME/jre的路径;
  这里要注意的是,如果真的要指定XjreOption,那么其路径值必须要用双引号包含起来
  */
private String xjreOption;//-Xjre 的路径;

然后写一个解析命令的方法,代码如下:

public Cmd(String[] args) {
    parseCmd(args);
}

接下来我们把方法实现一下,在实现之前我们可以思考一下,都要校验什么,命令参数的长度关键字语法,大概也就这些,好,我们开始干。代码如下:

首先校验基本格式:

int classNameIndex = 1;
if (args.length < 2) {
    //最简短的java命令:java -version,参数长度更小的,肯定不合法
    isRightFormat = false;
    return ;
}

接着判断java命令:

//接着判断开头是不是 java ,如果不是,证明不是可运行的java命令;
if (!"java".equals(args[0])) {
    isRightFormat = false;
} else {
    if ("-help".equals(args[1]) || "-?".equals(args[1])) {
        helpFlag = true;
    } else if ("-version".equals(args[1])) {
        versionFlag = true;
    } else if ("-cp".equals(args[1]) || "classpath".equals(args[1])) {
        //到这一步的命令不是cp就是classpath,所以长度至少有4个
        if (args.length < 4) {
            isRightFormat = false;
        }
        classNameIndex = 3;
        //由于该命令需要知道类路径,故添加字段
        this.cpOption = args[2];
    } else if ("-Xjre".equals(args[1])) {
        //如果走到这一步,那么命令行必定是java -Xjre "C:\Program Files\Java\jdk1.8.0_20\jre" java.lang.Object 的形式
        if (args.length < 4) {
            isRightFormat = false;
        }
        classNameIndex = 3;
        this.xjreOption = args[2];
    } else if ("-".startsWith(args[1])) {
       isRightOpt = false;
    }
    this.clazz = args[classNameIndex];
    this.args = new String[args.length - classNameIndex + 1];
    int argsIndex = classNameIndex + 1;
    for (int i = argsIndex; i < args.length; i++) {
        this.args[i - argsIndex] = args[i];
    }
}
//命令行格式错误,输出错误信息
public void printUsage() {
    System.out.println("Unrecognized option: --\n" +
            "Error: Could not create the Java Virtual Machine.\n" +
            "Error: A fatal exception has occurred. Program will exit.\n");
}

到这,一个命令类就定义完了,然后我们回到主程序。代码如下:

public class StartApplication {
    public static void main(String[] args) {
//        String s = "java -version";
        while (true) {
            System.out.println("please input java cmd:");
            Scanner sc = new Scanner(System.in);
            String inputCmd = sc.nextLine();
            System.out.println("input java cmd:"+inputCmd);
            Cmd cmd = new Cmd(inputCmd.split(" "));
            if (!cmd.getIsRightFormat()) {
                cmd.printUsage();
            } else {
                if (cmd.getVersionFlag()) {
                    System.out.println("java version "1.8.0_202"\n" +
                            "Java(TM) SE Runtime Environment (build 1.8.0_202-b08)\n" +
                            "Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)\n");
                } else if (cmd.getHelpFlag() ) {
                    System.out.println("这是帮助命令");
                } else {
                    System.out.println("欢迎来到JVM");
                }
            }
        }

    }
}

然后我们来看效果,图如下:

实践篇-Java命令参数解析


上一篇:判断单链表是否存在环


下一篇:什么是雾计算?它与云计算有什么区别?