前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java编译运行环境讨论(复古但能加深对Java项目的理解)

Java编译运行环境讨论(复古但能加深对Java项目的理解)

作者头像
w4ngzhen
发布2023-10-18 17:59:48
1860
发布2023-10-18 17:59:48
举报
文章被收录于专栏:编译思想

如今我们大多数情况都会使用IDE来进行Java项目的开发,而一个如今众多优秀的IDE已经能够帮助我们自动的部署并调试运行我们的Java程序。然而在早期我们进行Java开始需要手动的建立逻辑包(package)与目录来管理我们的Java项目或是更高级一点的则是使用ant这样的构建工具。作为Javaer,对于Java的编译过程应当是熟悉的,这样即使脱离了IDE我们依然能够很好的理解Java的构建过程。

初级

我们首先建立一个基础的项目文件夹java-demo,并在其中建立Main.java文件:

代码语言:javascript
复制
$ vim Main.java
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}
tips:
在Java中,.java文件中至多有一个共有类,并且文件名和改共有类相同,如果没有共有类,则任选一个类名作为文件名即可。

完成了我们的编辑工作之后,我们使用javac命令进行编译工作:

代码语言:javascript
复制
$ javac -d . ./Main.java
$ ls
Main.class Main.java
tips:上述的-d .表示在当前目录下生成class文件

之后我们可以使用java命令运行得到的.class文件(不需要带.class文件后缀)

代码语言:javascript
复制
$ java Main
Hello

初级++

在上述的示例中,我们并没有在代码中对我们的Java程序打包(package xxx;),我们知道Java中对程序进行package有很重要的意义:能够模块化程序,通过定义不同的包来实现模块化的开发,同时也能够帮助其他接手或者学习代码的人能够有很好的引导作用,能够明白整个Java项目模块的分布。

所以我们现在需要在代码中定义包,从而模块化我们的代码,这里我们在Main.java代码的第一句加上这样一句代码:

代码语言:javascript
复制
package src.main;
tips: 这句话代表了我先要把该Main类定义在包src包中的main包中

然后我们删除刚刚编译过的class文件,为了之后的生成class文件的删除方便,我们在java-demo文件夹下创建一个target文件夹,为以后的class文件的生成目标文件夹。

代码语言:javascript
复制
当前工作目录以及文件结构如下:
$ pwd
xxx/java-demo
# 目录结构
./
├── Main.java
└── target

接着我们重新编译

代码语言:javascript
复制
$ javac -d ./target Main.java
$ ls
Main.java target
进入target目录之后,我们可以看到如下的结构:
./
└── src
    └── main
        └── Main.class

我们可以看到,即使我们并没在原先的工作目录下创建src/main/Main.java这样的源码结构,只是在代码中定义了逻辑上的src.main,在javac之后,java会为我们自动生成这样的目录结构。

接下来我们通过java命令运行Main.class。这里有很重要的一点,通过我们上面的代码定义,我们最终生成的是一个名为src.main.Main类,不是单纯的名为Main类,不能像上面java Main那样去直接运行这个Java程序,同时我们应当在目标类生成的根目录下去运行java命令:

代码语言:javascript
复制
# 在target目录下
$ java src.main.Main(或者java src/main/Main)
Hello

即使我们进入到了target/src/main目录中(只要不是target/这样的目标根目录),直接使用java Main或者是java src.main.Main都是不行的。前者会提示:“错误: 找不到或无法加载主类 Main”, 原因就是我们定义是一个src.main.Main的类,很显然这里没有类名为Main的类;后者会提示:“错误: 找不到或无法加载主类 src.main.Main”,原因则是当我们使用java命令去运行譬如src.main.Main等在非默认包下的类时,java命令会自动将src.main.Main转换为 $classpath/ src/main/Main这样路径下的类文件,而你有没有定义classpath,那么java会在当前(这个例子就是main目录类),再找src/main/Main类,这里当然没有,所以报错。诚然,你可以在使用java命令时通过-classpath来指定类加载根路径,但是这样显然没有直接在类编译根目录下来的直接。

(初级++)++

目前为止,我们只讨论了只有一个类的情况,当我们在一个类中通过import来引入其他类的时候,又该注意什么呢?

首先我们重构整个文件目录结构如下:

代码语言:javascript
复制
xxx/java-demo
    ├── dir1
    │   └── Main.java
    ├── dir2
    │   └── Sub.java
    └── target

首先在Sub.java中我们编写如下的代码:

代码语言:javascript
复制
package myutil;
public class Sub {
    // 静态工具方法
    public static void printWithFormat(String str) {
      System.out.println(">>>" + str + "<<<");
  }
}

然后编写Main.java中的代码:

代码语言:javascript
复制
package main;
// 引入Sub类
import myutil.Sub;
public class Main {
    public static void main(String[] args) {
        // 调用Sub类中的静态方法
        Sub.printWithFormat("Hello");
    }
}

这里我们定义了dir1、2两个文件加,虽然和Main类与Sub类中package的包名不同,但是,当我们在编译时,只要指定了正确目录下的对应的java类即可,就像我们可以进入dir1类中使用如下命令:

代码语言:javascript
复制
$ pwd
xxx/java-demo/dir1
$ javac -d ../target/ ./Main.java ../dir2/Sub.java # 自行理解对应文件的位置关系

接着我们查看对应的target下生成的class文件:

代码语言:javascript
复制
target/
├── main
│   └── Main.class
└── myutil
    └── Sub.class

同样的,我们按照**初级++**中提到的,在根目录下,使用java main.Main命令,可以看到,没有问题:

代码语言:javascript
复制
$ java main.Main
>>>Hello<<<

关于java编译运行的路径相关的注意点大致就讲这些,以后会继续补充相关的更多的注意点。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-03-302,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档