前言
我在刚刚学习java时只是抱着高中时期的:”跟着老师走,我就能理解一切“的心态,按部就班按着老师所讲的去学习,并非没用,但也不能算很有用,学校的老师讲课会顾及难度,不会向我们去教导一些更深层次的东西,当我去问老师时,老师给的回答往往是让我去网络里寻求答案,对啊,现在是互联网的时代,ai遍布我们的生活各处,技术文档由众多大佬分享,于是我对于一些当时不是很理解的地方做了我自认为的“浅层深挖”,目的是为了帮助我更加去理解原理,而不是只是迷迷糊糊的做一个打代码工具。
一.为什么我们要去配置环境变量?
在我刚刚接触java的时候,老师课上交给我们的第一个任务,便是"配置环境变量",这对于还是萌新的我而言十分的困难,反复的配置失败以及一次次尝试让我不由得想:“为什么我们要配置java的环境变量呢?”
如图中,我在没有配置环境变量之前尝试在我的e:\train_code下去执行命令:
javac helloword.java ,结果弹出提示:“javac不是内部或外部命令,也不是可执行程序”。
为什么呢?为什么会出现“javac不是内部或外部命令”这个错误呢?我明明已经安装了java!
原来在未配置环境变量时,系统无法在任意路径下找到javac.exe
,因为系统默认只在当前目录和path
环境变量指定的路径中搜索可执行文件。在环境变量没被配置时,系统根本不知道javac.exe到底在哪里。
javac.exe通常藏在 c:\program files\java\你的jdk版本名称\bin 里面
而我如果需要运行我的.java程序,我需要jdk(java development kit - java开发工具包)中bin目录下的javac.exe来对.java程序进行“编译”,那么我想你应该有一些理解了,之所以要配置环境变量,是为了使得我们的这个.java程序无论位于我们电脑的哪个盘符(c: / d: / e:........)下的哪个文件下,都可以通过javac.exe来进行对.java程序的“编译”。
环境变量path的配置,配置path
后,无论当前目录在哪里,系统都会在c:\program files\java\jdk-xx\bin
中搜索javac.exe
,可以理解为就是将我所配置的这个路径当作一个环境,我执行哪个文件都相当于是我在这个环境下去执行的,当然也就能使用这个环境内的工具了,所以我们并不是不配置环境变量就无法运行java项目,配置环境变量后,我们就可以在任意目录下编译和运行java程序,无需每次切换到jdk的bin目录。
二.“编译”是什么过程?java程序又是怎么样去执行的呢?
在“一”里面我们提到了一个词,叫做“编译”,这个词本身我们是没少听的,我们常说编译器,编译器,难道编译的作用就是把程序在我们的计算机运行吗?事实上,编译只是我们程序运行这个大过程中的一个小过程,举个例子,比如运行c语言程序,我们并不是只依靠编译去运行这个程序,而是先通过编译将开发者写出的这些由英文字母组成的代码,转换为机器所能看懂的二进制的机器码,然后再由机器去执行这个二进制的机器码,但是java呢?java也是这样吗?
实则不然,java程序的运行过程要更多一点,因为java拥有一个优势:那就是java可以实现跨平台,通常称之为“一次编写,到处运行”(write once, run anywhere, wora)。
1.为什么java可以实现跨平台而c/c++不行呢?
c/c++都是直接由对应操作系统的编译器来编译为.exe的可执行文件,之后直接运行的,他们所生成的这个.exe里面都是针对特定平台的机器码,所以c/c++并不能够实现跨平台运行,windows的.exe就是windows的,linux的就是linux的。
2.java的运行过程较为特殊,java的运行过程为:
首先,开发者写出一份.java程序,拿给环境变量里的jdk说:“我这里有个java程序,请你帮我运行他。”,然后jdk中的javac.exe就会把你给他的java程序编译为一份.class的字节码文件(.class文件就是java实现跨平台的关键),并且对你说:“这个你得等我会儿,我这里呢得先处理下你的程序,然后交给统一部门对你这个程序做更细化的处理。”
然后,这个.class文件会被交给jvm,jvm类似每个手机厂商分布在各个城市的手机专卖店,虽然门店服务的地区不同,但是门店都是这个手机厂商旗下的,也就是说虽然不同操作系统下的jvm是不同的,但他们都有一个相同的“接口”来使得他们能以不同的jvm实现来达成同一个功能:那个功能就是他们都能够将这个.class文件进行动态解释或者编译执行
关于java与c/c++的运行过程(更清晰的展示):
c/c++:源码 → 编译为平台特定的机器码 → 直接运行。
java:源码 → 编译为平台无关的字节码 → jvm解释/编译执行。
字节码文件的核心作用:
跨平台(平台无关性):一次编译,jvm运行(windows/linux/mac通用)。
安全可控:jvm检查代码,防止崩溃或病毒。
统一生态:java/kotlin等语言最终都变成字节码,互相兼容。
高效执行:jit编译热点代码,速度接近c++。
一句话总结:字节码是java跨平台的“通用语言”,由jvm翻译执行,兼顾安全性和性能。
三.java最基础的程序代码
public class main { public static void main(string[] args) { system.out.println("hello, world!"); } }
我所打的第一个java程序,便是这个“hellow,world!”,我一开始就对这个神奇的东西很不理解,这个string[] args是个什么玩意?main前面这一大串又是啥啊?
关于main
main方法是一个特殊的方法,它定义了java程序的起始位置。如果没有这个方法,jvm就无法启动程序。如图,可以看到,如果一个程序中没有main方法,那么这个程序甚至无法运行。
注意,这里说无法运行并发完全无法运行:
java 9+支持模块化启动,可通过
jlink
定制启动类。但初学者场景下,main仍是标准入口。
关于string[] args
main方法不只是一个简单的入口,他里面传入的参数,也就是:string[] args参数(事实上,string[] args作为一个参数,参数名并不强行要求为args,你甚至可以把它改成aaas),但要注意:
虽然args可以改名,但约定俗成用
args
,提高代码可读性。其他常见命名如
argv
(来自c传统)。
程序可以通过这个参数来处理用户输入的动态数据,string[] args中存储了当该程序在终端或者命令提示符中运行java程序时,人为通过命令添加的额外参数,比如我在终端中执行:
java 类名 参数1 参数2 ...
那么这个时候,arg[0] = "参数一",而arg[1] = "参数二",让我们来验证一下吧:
public class myprogram { public static void main(string[] args) { // 获取参数数组的长度 int numargs = args.length; system.out.println("命令行参数数量: " + numargs); // 遍历并打印每个参数 for (int i = 0; i < numargs; i++) { system.out.println("args[" + i + "] = " + args[i]); } } }
我们在终端执行 java myprogram "hellow world" 123 ,我们运行程序会输出:
命令行参数数量: 2 args[0] = hello world args[1] = 123
关于system.out.println()
当我写出代码时,我看着我打印出来的hellow,world!陷入了一个思考,为什么这个名为system.out.println的东西能够将它后面括号内的内容打印出来呢?
这里面,system
是jdk提供的工具类,out
是其静态字段(类型为printstream
),println
是printstream
的方法。这些代码是java标准库的一部分,初期只需知道它是输出语句,后期可深入研究io流和标准输出的设计.
当我们的鼠标按住“ctrl”键的同时将鼠标指针移到这三个单词的任意一个上面时,他会被高亮,这个时候我们点进去,你就会发现:
它跳转到了一个我们不知道的地方,这里就是jdk的源代码,我们的这个语句就是在这里被定义的,所以本质上我们只是将大佬们定义好的方法拿过来去使用。
个人想说的话:
到此这篇关于java入门学习之环境变量与程序运行原理的文章就介绍到这了,更多相关java环境变量与程序运行原理内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论