Java应用程序需要有一个入口,而这个入口就是main()
方法,包含main()
方法的这个Java类叫作主类。JVM规范并没有规定哪个类是主类,所以我们可以自己创建一个主类,只要包含main()
方法即可。
虽然我们可以自定义一个主类,但是如何告诉JVM哪个类是主类呢?实际上JVM是通过java命令来加载并启动主类,主类名可以由命令行参数指定
我们在cmd
命令窗口执行java
命令
从回显中可以看到java命令的具体用法
java [-options] class [args...]
(执行类)
java [-options] -jar jarfile [args...]
(执行 jar 文件)
以执行类为例,用法表明可以向这个java命令传递三个参数:
[-options]
:选项class
:主类名(告诉JVM哪个类是主类)[args...]
:main()
方法参数(可传递多个参数)
其中选项可以分为标准选项和非标准选项,非标准选项以-X
开头
java命令可以加载并启动主类,我们首先需要根据java命令的第一种执行类的用法,实现一个命令行工具用来解析执行java命令
首先需要定义一个结构体用来表示命令行选项和参数
/*命令行选项和参数的结构体定义*/
type Cmd struct {
helpFlag bool //帮助选项,输出帮助信息
versionFlag bool //版本选项,输出版本信息
cpOption string //目录和 zip/jar 文件的类搜索路径,用于搜索类文件
class string //主类名,用于指定主类
args []string //参数信息
}
一个命令行结构体,我们就可以描述一个java命令,同时还需要能够解析这个java命令。所以要定义一个解析命令行的函数
/*Go语言内置了`flag`包可以用来处理命令行选项,`os`包中定义了`Args`变量,其中存放传递给命令行的全部参数*/
func parseCmd() *Cmd {
cmd := &Cmd{}
//编写printUsage()函数,用来输出到控制台
flag.Usage = printUsage
//Var函数用来设置需要解析的选项
flag.BoolVar(&cmd.helpFlag, "help", false, "print help message")
flag.BoolVar(&cmd.helpFlag, "?", false, "print help message")
flag.BoolVar(&cmd.versionFlag, "version", false, "print version and exit")
flag.StringVar(&cmd.cpOption, "classpath", "", "classpath")
flag.StringVar(&cmd.cpOption, "cp", "", "classpath")
//调用Parse函数解析选项
flag.Parse()
args := flag.Args()
if len(args) > 0 {
cmd.class = args[0] //第一个参数是主类名
cmd.args = args[1:] //从第二个参数开始往后,都是main()方法的参数
}
return cmd
}
func printUsage() {
fmt.Printf("Usage: %s [-options] class [args...]\n", os.Args[0])
}
Go程序的入口也是main()
函数,所以需要创建一个go文件,里面包含main()
函数,然后调用parseCmd()
函数解析命令行参数,如果解析成功就调用startJVM()
函数
func main() {
cmd := parseCmd()
if cmd.versionFlag {
fmt.Println("version 1.0")
} else if cmd.helpFlag || cmd.class == "" {
printUsage()
} else {
startJVM(cmd)
}
}
func startJVM(cmd *Cmd) {
fmt.Printf("classpath: %s class:%s args:%v\n", cmd.cpOption, cmd.class, cmd.args)
}
执行编译出来的exe
文件并测试
至此就实现了一个简单的用来解析java命令的命令行工具
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)