【Java学习】剖析Java程序的层次组织与多文件连接

本文介绍了Java程序的层次组织,包括项目、包、源文件和类的关系,强调了类的公共与非公共、主类的概念。讨论了源文件与类文件的对应规则,并解释了包的作用、package和import语句的使用。此外,还讲解了Java编译时如何处理多文件的依赖,重点在于编译器如何查找和处理.class文件。

0 前言

最近重回Java了,先梳理一下Java的文件组织和一些编译上的连接逻辑。
这篇博客适合刚接触Java,能编写简单的Java程序,或者像我一样忘了Java文件的组织逻辑的菜鸟。这里没有语法知识,那些到处有,我更多的是讲一下逻辑和思想

1 层次概念

Java中文件组织层次为:项目(project)>包(package)>源文件(file)>类(class)。这里自底向上梳理一下

1.1Java中的类

类是Java程序的基本组成。Java中的类在结构上又有公共类,主类、内部类之说。这里旨在说明类的结构思想,不谈及类的定义。

1.1.1万物皆可为类

Java与C++都是面向对象编程语言,都有类的概念。但是,如果你跟我一样是从先学了C++再接触Java,那你初见Java版HelloWorld时一定跟我一样一脸懵逼。

public class HelloWorld{
    public static void main(String args[]){
        System.out.println("Hello,world!");
    }
}

为什么一上来就定义一个类?
main函数为什么写在类里面?
这个Java的程序结构有关。

Java程序都是且只能由类组成。

这句话可以理解为:Java所有变量,函数都要写到类定义里去。Java程序入口就是类,整个过程就是类之间的协作。
什么?全局变量?全局函数?通通写到类里去,静态(static)变量,静态函数不会吗!
所以,从C++过来刚接触Java的同学,你需要一种不同于C++的思想

万物皆可为类

可以这样理解,不同于C++,Java诞生的时候面向对象编程思想相对成熟了。除了具有实际意义的物品能定义成对象,甚至行为、属性等也可以给它一个负责执行和管理的抽象类。
这样,HelloWorld可以这样理解:首先我们定义了一个HelloWorld类,这个类负责执行main函数。
随着你对Java的深入接触,你会渐渐觉得这种思想很受用。

1.1.2 公共类、非公共类与主类

先给出定义:

公共(public)类与非公共类:在类定义前有public关键字的类为公共类,没有的为非公共类。
主类:含有主函数(main)的类称为主类。主类是程序的入口

大部分情况下,一个程序只有一个入口类,而且这个类往往是公有的。
【注意】:

  • 主类不一定是公有类
  • 一个Java程序允许有多个主类,也就是存在多个main函数,但一个类中只能有一个main函数。 这可能很奇怪,不过Java程序执行的时候是需要指定入口类的,所以并不会冲突。
    可以看这个例子:
/**
HellowWorld.java
**/
public class HelloWorld{
    public static void main(String args[]){
        System.out.println("Hello,world!");
    }
}
class NotHelloWorld{
    public static void main(String args[]){
        System.out.println("This is 'Hello,world!'");
    }
}

在这里插入图片描述
【疑问】从上面的例子中发现一个问题,既然非公有类是包内可访问的,那为什么还有public函数(main)?包外可以使用这个函数吗?
【回答】这貌似确实冲突了。首先,包外无法访问这个类的,当然无法使用这个函数。但是,我们不得不保留这种表达,因为这个非公有类(或匿名类)可能实现了某个公共接口。

1.2 源文件(.java)与类文件(.class)

1.2.1 源文件与类

Java中源文件与Java类是具有对应关系的。它们之中最重要的联系就是:

源文件主名(不包括后缀.java)必须与公共类名一致。

【注意】一个源文件内可以定义多个类,但只能有一个公有类。
往细了说,就是:一个源文件至多可以有一个公共类和任意个非公共类。如果有公有类,必须和文件名一致,否则会报错;如果没有,文件名可以任意。
在开发中,一个Java源文件往往包含一个同名公共类,所以我们常常用该公共类指代该文件。

1.2.2类文件与类

Java编译生成的文件为.class文件,文件名一般与类名相同。

.class文件与类是一一对应的。

不论该类是否公有,甚至对于匿名内部类,都会生成与之对应的.class文件。如果在一个文件中定义了多个类,编译会得到多个.class文件。

1.3 包

包是Java中文件的组织结构。类似于文件系统中文件夹机制对文件管理的作用,而且包路径实际上也是对应源文件的存放路径

1.3.1 包的作用

  • 把功能类似的类组织在同一个包中,方便查找与使用。
  • 避免重名冲突。允许在不同的包中存在名称一样的类。
  • 限定访问权限,支持Java提供的包内访问选项。

1.3.2 package语句

Java通过package语句实现包机制。package语句指定了该文件中所有类的路径

pakage语句必须在文件最顶部(不含注释),否则编译报错。
pakage语句中的包路径必须与源文件的存放路径(相对于项目根路径)一致,否则在引用时会报错。

【疑】既然文件已经放到相应的位置了,为什么还需要pakage语句显示声明?
【答】 尽管放到正确的包路径中,没有pakage声明的文件中的类在编译过程中会被放到默认包(未命名)中,无法被引用。
所以,你必须保证,源文件的存放路径与package语句中的包路径都正确且一致

1.3.3 import语句

在一个类中引用另一个类可以使用包名+类名或者通过import语句引入后直接使用类名。

import语句位于package语句与类定义之间。

【注意】
引用同一包内的类不用import语句,否则会报错,编译器会自动查找包类定义的类。但是如果没有package语句声明,即使同一个路径下的两个类也无法相互引用。也就是说没有package语句的类是找不到的,记住一句话:

没有package(语句),就不能被import。

2 多个文件的编译

我们知道C/C++通过#include包含文件实现文件的链接。那Java呢?

2.1 需要多文件一起编译吗?

先提一下,Java可以使用通配符一次编译多个文件。
javac A*.java可以一次性编译以A开头的所有文件。
但是,一般情况下,我们只想编译一个主类以及它依赖的所有类。这种时候只需编译这个主类就可以了。

Java在编译一个类时,会自动查找并编译(如果需要的话)其引用的类文件。

2.2 去哪里找依赖类呢?

----答案是-classpath。很熟悉?就是JDK安装时候配置的系统变量
在这里插入图片描述

2.3 找什么?

----上面说过的两个文件,.java文件和.class文件。

  • (多数情况下)如果只找到.java文件,编译之。
  • 如果只找到.class文件,使用之。
  • 如果找到二者,检查时间截,若发现.java文件修改过,重新编译生成最新的.class文件。
    所以,如果类A引用了类B,且二者都编译过存在对应的.class文件,然后同时修改二者之后,你只需要编译类A,编译器会自动更新类B。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值