001_HelloWorld入门

Java语言的运行机制

高级语言的执行模式

纵观整个it的发展史,刚开始是没有高级语言的,只有"机器语言",类似于跑在单片机上那种机器可以直接识别的代码指令。机器码执行效率很高,但是编写代码很费劲,开发效率和可读性都很差。我是机械专业的,接触过这种编程.。被逼着写机器码的那段日子实在是苦不堪言,那个时候觉着这个东西根本不是人玩的。世界上大部分人肯定和我有着一样的想法,其中又聪明又懒惰的哥们儿就开始动脑筋,一步一步把机器码的编程逐步转换为对人类友好的编程模式,然后各种富有语义化的编程语言就诞生了。
利用高级语言写出来的代码就像是文章一样,人很容易就能读懂,但是机器没那么智能,肯定不能理解你写的是什么东西。要解决人能看懂但是机器看不懂的问题,就需要引入【翻译】的能力,也就是将人能理解的代码转变成机器能理解的代码。【翻译】的过程称为编译,而编译这个行为可以在两种时间节点上发生,这也就是我们描述编译的两种执行模式:

  1. 编译型执行方式
  2. 解释型执行方式

第一种:编译型执行方式
机器在嗷嗷待哺,我们把我们写好的代码整个全部翻译下来,然后一口气喂给机器,机器就知道你要干什么了。C或者C++,就属于这种编译执行。
第二种:解释型执行方式
机器在嗷嗷待哺,我们把文章一句一句翻译好喂给机器,机器也能理解,这种方式就是解释型执行方式。当下很多脚本语言,例如python,shell就是这么玩儿的。
简单的来说解释型执行方式启动快,但是执行过程慢一些,编译执行刚开始要花很多时间做编译,但是后面执行快一些,毕竟后面执行的都已经是机器码了。

语言种类分类

高级语言种类分类是以字段类型定义是否可变来展开的,和语言的执行模型没有直接的联系。
第一种分类:动态语言
动态语言也叫动态类型定义语言,在执行期间才去发现数据类型的语言,这也就意味着在运行时可以改变字段类型,甚至新的函数可以被引进或者删除。动态语言不需要写非常多的类型相关的代码,因此方便阅读,但是如果开发者开发素质不高,命名不规范时反倒不利于理解。
第二种分类:静态语言
静态类型要求在使用所有变量之前要声明它们的数据类型。有了更多信息之后,可以在编译态就行完整验证代码的正确性,这样一来可以在一定程度上保证代码质量,其结构较为规范。但是这种事儿干多了,代码会显得很啰嗦。

Java执行方式

Java是静态语言,代码会在编译的时候进行完整翻译。但是Java代码的执行模式是混合式的,也就是说编译型执行方式和解释型执行方式都有。
java编译之后生成的不是直接的机器码,而是字节码(.class文件),然后将这个字节码文件文件给到JVM,而在各个平台上(windows,linux等不同的操作系统)的Jvm实现不一样,但是可以接受同一份.class,这就要求字节码文件的格式必须是固定的。JVM的作用就是将平台进行屏蔽,这样一来,就可以做到,"一次编写,到处运行"的特性,相同的java代码,至于能不能得到相同的结果全靠各个平台上的JVM的实现。
反观JVM,它是C实现的,在其内部事实上是将字节码指令一行一行地进行执行,相当于是解释执行的特性。当然这样会导致效率问题,毕竟在运行时做了各种翻译。为了弥补这个短板,JVM造了C1,C2编译器,在代码运行一段时间之后,发现一部分代码经常执行,那么就将这一部分代码直接转变成机器码,丢给CPU直接执行,这就是编译执行的特性。

HelloWorld程序

对于一门语言来说,HelloWorld例子是很重要的,虽然HelloWorld很简单,但是真的深入下去,什么话题都可以连带出来。
例如,为了保证java代码编译不报错,那么就需要有java代码的基本规范。javac指令会编译你的代码,解析为字节码文件,这个过程牵扯到编译原理。虚拟机是对字节码文件有格式上的要求的,那么这里就有个字节码规范。字节码在JVM内能跑起来,JVM自己也是有执行的规范的,有了这种规范之后,各种厂商就可以按照这样的规范自己实现JVM。如果考虑JIT即时编译器的学问,那么就需要了解计算机组成原理,知道CPU是怎么使用各种晶体管搭建出来的。
见微知著的概念,也体现在这里了。任何一门语言,任意一个小点,深究下去都是一大块儿一样的知识,而大部分深入的知识都被前人们封装了,你只需要写高级语言代码来指导计算机帮你干活就行。这些深入的知识平时工作基本用不着,但是却是区分高级工程师和弱鸡工程师的门槛。当你对底层足够了解的时候,你写的每一行代码都会脑补出这行代码是怎么跑起来的。

简单的HelloWorld

执行java需要先安装JVM,在此不做介绍,网路上相关教程相当多。接下来我们分步骤手动执行一下java代码、
**第一步:**在test目录下,使用任意一个文本编辑器,写下以下代码,并保存为.java格式的文件。

/**
* HelloWord 程序
* */
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("hello word");
    }
}

**第二步:**执行 javac + java代码路径名,在当前目录下新增一个HelloWorld.class文件。
**第三步:**执行 java HelloWorld,你会看到打印出Hello world的字符串。
如图:
image.png

javac 是拿来编译(编译 .java文件 生成 .class)用的, java 则是执行(执行 .class文件)用的。

编译与执行的各种问题

Helloworld一个简单的demo,只要死死的按照上文操作一遍当然没啥问题。回顾刚开始自己学java的时候,爱折腾,这里不行,那里不对,哪哪都碰壁,接下来给大家说说我之前遇到的囧事儿。
我把HelloWorld的类名改成HelloWorld1,如下代码所示

/**
 * HelloWord 程序
 * */
public class HelloWorld1 {
    public static void main(String[] args) {
        System.out.println("hello word");
    }
}

当进行javac编译的时候,报错。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
看错误信息,告诉我你的文件名要和类名一样,什么奇怪的规定!一气之下把public给删了

/**
 * HelloWord 程序
 * */
class HelloWorld1 {
    public static void main(String[] args) {
        System.out.println("hello word");
    }
}

然后编译,执行,打开文件目录,发现.class文件也出来了
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
很难受,不知道为啥,愁死我这个初学者了,然后后来才知道,这里头有个规范:

一个.java文件里 public的类的数量 <=1

那么这样意味着,public的类可以没有,不带public的类可以有很多个。ok,没问题,那我继续整。
学着学着发现,原来我们的java是可以分包的,那我改成这样:

package com.zifang;
/**
 * HelloWord 程序
 * */
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("hello word");
    }
}

然后执行编译指令
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
又挂了,这玩儿说找不到main函数?我就加上了包,怎么就出问题了呢?后来找啊找,初学者体验爆炸,一步一个坑。后来我在test路径下找HelloWolrd的类,灵光一闪,修改指令变成 java com.zifang.HelloWorld,然后呢,以当前目录为根目录,用包路径去找.class的路径。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
这样也就执行了。回过头来,你会发现还是很成问题的,我javac在test目录编译 com.zifang.HelloWorld的代码,HelloWorld文件放在当前目录,不应该吧,java代码也应该放在com/zifang下才对啊?ok,我们放进去
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
这个时候,编译指令又出问题了,应该写个啥?我在文件夹里面写还是在test根目录写?
感觉一下,应该要放在外面,万一我在文件夹里面不光就只有一个类呢?在test文件夹目录应该可以批量编译,不然一个一个也太累了。就这么办,我相信前辈们肯定想过这个问题。
javac com.zifang.HelloWorld.java ?  好像有点不伦不类
javac com.zifang.HelloWorld?  还是怪怪的,试一把?不行,我们再换
javac com/zifang/HelloWorld.java ?  不确定,试试,好像可以,nice!
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后怀着忐忑的心情,尝试一把

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
可以,不错,正常了。
如果类一多,那我还要考虑批量编译,这也是个问题。刚刚编译的时候,编译出来的.class和.java是放一起的,对我这个有洁癖的人来说,太难受了,.java是源代码,.class是编译后的代码,不应该放一起。找啊找啊,找我的解决方案。发现javac的参数-d好像能帮助我。
我们把.java的代码全部塞到src目录下,标识这里面全是源代码,然后和src同级新建一个classes的文件夹,表达里面全是class文件。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

javac -d classes com/zifang/HelloWorld.java

摸索了一下,写出上面的指令

image.png

没问题,正常把class生成出来丢到classes里面去了。那么执行呢?

image.png

又出问题了。按照之前的想法应该写成,java classes.com.zifang.HelloWorld,但是这样不对,classes.com.zifang.HelloWorld又不是类的包名,这里应该有个参数指明了要以哪个文件夹为基准目录,伴随着这样的想法,慢慢找,找到了-classpath的参数,使用这个参数告诉jvm你去这个文件目录找去。尝试一把

image.png

的确可以,舒服了。

那么就剩下最后一个问题了,这会儿不是也就鼓捣一个类吗,如果有很多类的话,我总不能一个一个去编译吧,这也太反人类了。怀揣着对美好世界的美好向往,百度搜一搜~失望,还真没有,策略有两种,你的编译指令后面写上一大堆文件路径,如果是用一个目录,那可以用*进行批量匹配。

// 如果src/com/zifang/下面就一个类
javac -d classes src/com/zifang/HelloWorld.java
// 如果src/com/zifang/下面有HelloWorld.java和HelloWorld2.java
javac -d classes src/com/zifang/HelloWorld.java src/com/zifang/HelloWorld2.java
// 上面的也可以写成(但是只限于一个文件夹,不做递归)
javac -d classes src/com/zifang/*.java

失望~没有简单的批量指令,只是形式上的缩成一行的执行方式,这样很难受。那能不能让我从频繁编译中解放?

——构建工具就这么出现了。构建工具的出现就是为了帮你管理项目目录,怎么编译给他一点配置就成,他帮你完成所有的事儿。(详细的使用方式后面会详细的描述,单独成篇)目前用的比较多的是 gradle(安卓开发用的多,新一代的构建工具),maven(用的人也相当多),ant(没人用了吧,知道有这么个东西就成)。

Maven的简单应用

上文提到了很多构建工具,为了故事的完整性,在此把怎么制造一个maven应用描述一下。maven的世界也很大,这里写不下。后面会开单独的部分去仔仔细细描述maven。目前使用的ide是idea。
第一步,new 一个project
image.png
然后你会得到一个大的选择列表,这里选择maven,右边会有很多模板,但是不重要,直接next
image.png
然后就会有一个关键性的界面了
image.png
对于强迫症患者而言,前两个也很重要。我的项目在本地都是规划好的,该怎么放,名字应该是个什么,虽然没什么限制,但是自己看着舒服,“家”里很干净的感觉。后三项,就比较关键了,我们称为GAV信息。这个信息相当于是一个坐标的概念。坐标是描述一个世界的,maven的世界对应的就是一个地儿,里面放着大量可以使用的共享的包。然后呢,你的项目引用了这个"坐标"也就可以用了,这个过程都是maven帮你搞定。
那你会问,我的坐标会不会和别人撞呢?当然有可能。这还是回到坐标和世界的概念。maven有个全世界程序员共享的世界,那自然这个里面的坐标必须是唯一的。你想在这个上面共享一些东西,如果发现坐标已经被占了,你只能改一改自己的项目的坐标了。一般我们造出来的应用去依赖别人的包,一般都会从这个最大的共享仓库上找。如果我们想发布自己的共享包到这个世界级共享仓库上,就要各种申请,配置,要做的事儿还是蛮多的。
那有没有不和别人共享的那种?有,就像公司里面自己搭建的"世界",名字叫nexus,然后通过一些配置,将自己的应用分享到这个私有的仓库上。
接下来,我们来看看GAV各项都有什么含义:

  • **GroupId:**groupId一般分为多个段,两段可能常见一些,第一段为域,第二段为公司名称。域又分为org、com、cn等等许多,其中org为非营利组织,com为商业组织。举个apache公司的tomcat项目例子:这个项目的groupId是org.apache,它的域是org(因为tomcat是非营利项目),公司名称是apache,artifactId是tomcat。
  • **ArtifactId:**描述这个应用是个啥,在你的这个组织(groupId)下,叫这个名字的项目就一个,保证组织内不冲突
  • **Version:**比方说别人依赖了你的包,然后一直用着。然后呢,你把依赖包的代码一改,传上去,然后别人在项目里一刷新,就换成了你改过之后的代码,然后应用炸了。这个事儿是需要避免的,因此引入版本(version)的概念,但凡你想部署一个包,你就需要给她一个名分,定格在那里,永不改变。但是这么一来,还是会很麻烦,写共享包的人,总不能每次想发一个版本,版本号就往上走一个?对于引用包的人来说,也麻烦,总要主动地升下版本才能用到最新的。可以看到,两者有矛盾,因此引入snapshot和release的区别,让你可以自主选择,"用最新代码"的策略方式,是自动就拿到最新的还是关注稳定。

通过这种方式制造出来的maven项目的结构长这个样子。

├── README.md
├── pom.xml
├── src
│   └── main
│       ├── java
│       │   └── com
│       │       └── zifang
│       │           └── ex
│       │               └── bust
│       │                   ├── charpter1
│       │                   │   ├── case1
│       │                   │   │   └── HelloWord.java
│       │                   │   └── case2
│       │                   └── charpter2
│       └── resources
└── target
    ├── classes
        └── com
            └── zifang
                └── ex
                    └── bust
                        └── charpter1
                            └── case1
                                └── HelloWord.class

这里的pom.xml就是maven项目的依赖,就靠这个文件进行项目管理,浓缩了前辈们的智慧。源码按照规范放在src/main/java下,编译出来的.class将会放在target/classes下。
这里的pom.xml文件长这个样子。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zifang</groupId>
    <artifactId>ex-bust</artifactId>
    <version>1.0-SNAPSHOT</version>

</project>

project是根目录,project的attributes是默认生成的,modelVersion描述这个POM文件是遵从哪个版本的项目描述符。接下来就是GAV信息。

在这个项目下制造一个HelloWorld类,在绿色的小三角形的地儿,就相当于启动了

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里一定要有一个概念:ide无非就是个工具,你必须了解这个工具背地里都帮你干了些什么事情,不然你的知识就全部绑定在了ide上,这是很要命的。点开输出面板里面灰白色的一行

/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=49459:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/tools.jar:/Users/zifang/workplace/idea_workplace/JavaBust/target/classes com.zifang.ex.bust.charpter1.case1.HelloWord

我们整理下个语句,看看这个语句的结构

/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/bin/java 
-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=49459:/Applications/IntelliJ IDEA.app/Contents/bin 
-Dfile.encoding=UTF-8 
-classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/charsets.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/deploy.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/dnsns.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/jaccess.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/localedata.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/nashorn.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunec.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/zipfs.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/javaws.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jce.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfr.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jfxswt.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/jsse.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/management-agent.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/plugin.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/resources.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/rt.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/ant-javafx.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/dt.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/javafx-mx.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/jconsole.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/packager.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/sa-jdi.jar:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/tools.jar:
/Users/zifang/workplace/idea_workplace/JavaBust/target/classes 
com.zifang.ex.bust.charpter1.case1.HelloWord

这么一来,你就会发现这个结构是:

/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/bin/java 
-javaagent:一个路径
-Dfile.encoding=UTF-8 
-classpath 
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/下的一些必要的jar包:
/Users/zifang/workplace/idea_workplace/JavaBust/target/classes 
com.zifang.ex.bust.charpter1.case1.HelloWord

首先,是java指令,这里直接变成绝对路径,怎么获得的呢?我们之前配置了JAVA_HOME,系统就知道你的java指令在哪了

  • -javaagent比较复杂,你只需要知道这是jvm级别的代理,jvm启动之后,每个class文件都会经过这个agent,然后做字节码改写,然后就可以完成非常厉害的机制,例如skywalking的全链路监控。后面在字节码的篇章会详细介绍这个厉害的机制。
  • -Dfile.encoding 表达文件编码格式
  • -classpath 前文我们在摸索的时候已经知道了,就是指明了你要跑的类都要在哪个目录下找,包括它的各种依赖,这里也包含了target/class路径。

最后一行是真正的期望跑起来的类。ide帮你干的就是把指令生成出来,然后帮你执行一把(ide帮你运行,maven指导编译,谁来指导maven要那么编译?也是ide在这中间和pom.xml的协作的结果。

小结

至此,我们知道了java代码如何依赖原生的指令进行编译与启动,也稍微介绍了下maven项目制造与idea的执行。
ide只是工具,你要运用它完成你所想的东西,而不是反过来受其牵制,丢了灵魂,成了傀儡。

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值