【Java13】包

“包”这个机制,类似于分组。主要作用是区分不同组内的同名类。例如,高三三班有一个“王五”,高二八班也有一个“王五”。高三三班和高三八班就是两个不同的包。

Java中的包(package)机制主要提供了类的多层命名空间,用于解决类的命名冲突、类文件管理等。

类似于C++中的命名空间namespace

如果希望把一个类放在指定的包结构下,应该在Java源程序的第一个非注释行声明:

package packageName;

一旦如上声明,这个源文件中所有定位的类都属于这个包。

如果其他人要使用这个类,需要使用这个类的完整名称:包名+类名。

// 文件:Hello.java
package lee;
public class Hello
{
  public static void main(String[] args)
  {
    // TODO
  }
}

如果使用如下命令来编译

javac -d . Hello.java

按道理,-d是指定编译结果.class文件的位置,这里指定是当前目录(.),但实际上是在当前路径下创建了一个文件夹lee,里面包含Hello.class。

这是因为,Java规定位于包中的类,在文件系统中也必须有与包名层次相同的目录结构

但是,如果直接使用javac Hello.java不会创建lee文件夹。这样做也属于挑战智商的行为,一般还是推荐使用-d,让它形成层次目录结构。

在执行的时候,需要给出这个类的完整名称:

java lee.Hello

虚拟机在装载lee.Hello类时,会依次搜索CLASSPATH环境变量所指定的系列路径,查找这些路径下是否包含lee路径,并在lee路径下查找是否包含Hello.class文件。同一个包中的类不必位于相同路径下,只要它们都在CLASSPATH环境变量中即可。例如lee.Person可以在C盘中,lee.PersonTest可以在D盘中。

另外,除了类文件组织成层次结构外,源文件也要组织成对应的层次结构。此外,建议把源文件和class文件分开放:

在这里插入图片描述

把class文件放到某个目录下,并不意味这个目录成了这个类的包名。必须在Java源文件中声明package来指定。

Java包机制运行需要两个条件:

  1. 在源文件中打包(package packageName);
  2. class文件位于对应路径下(这个一般通过编译器来自动管理)。

对于包重名的情况,建议包也可以通过层级来组织,比如org.crazyit.elearning.student.lee云云。

package的使用有如下注意事项:

  1. 必须是源文件中非注释的第一句;
  2. 一个源文件只能指定一个包;
  3. 如果没有显示指定包,则类位于默认包下;
  4. 同一个包下的类可以自由访问。
// HelloTest.java
package lee;
public class HelloTest
{
  public static void main(String[] args)
  {
    // 直接访问相同包下的类,不需要使用包前缀
    var h = new Hello();
  }
}

如果在lee包下再定义一个子包,那么子包中的类不能直接访问lee包中的类了。此外,在使用子包中的类时,要使用该类的全名(包名+类名),不能省略前面lee包的路径。

package lee.sub;
public class Apple{}

lee.Hello中使用Apple类时,必须用完整路径lee.sub.Apple

可以这么理解:父包和子包从逻辑上存在上下关系;但是从用法上没有任何关系。所以调用时要使用完整包名+类名。

package lee;
public class Hello
{
	public static void main(String[] args)
  {
    var a = new lee.sub.Apple(); // 使用完整路径
  }
}

为了简化对不用包的类的调用,Java引入了import关键字。import可以导入指定包层次下的某个类或全部类。

  • importpackage之后,类定义之前;
  • 一个Java源文件只能有一个package,但是可以有多个import
import lee.sub.Apple; // 导入lee.sub中的Apple类
import lee.sub.* 			// 导入lee.sub中的所有类

使用import后,在当前源文件中就不用再输入完整路径了。

这一条和C++中的using namespace类似。

Java默认所有源文件都导入了java.lang包下的所有类。所以String, System类不需要显示的import。

import语句可以简化编程,但并不是必需的

JDK 1.5之后,还允许使用import导入类成员变量、类方法,区别在于加上了static修饰符:

import static package.subpackage.className.fieldName|methodName;

例如,使用import static导入java.lang包中System类和Math类的所有静态成员和静态方法(类成员和类方法):

import static java.lang.System.*;
import static java.lang.Math.*;

public class StaticImportTest
{
  public static void main(String[] args)
  {
    // out是System的成员方法;
    // PI是Math类的成员变量;
    out.println(PI);
  }
}

现在总结Java源文件的大致结构:

package 语句;  // 0或者1条,位于文件非注释行的最开始
import | import static 语句; // 0条或者多条,位于package之后,第一个public类定义之前
public className | interfaceName | enumName; //0个或者1个public类、接口或枚举,注意一个源文件只能有1个public类
className | interfaceName | enumName; // 0个或多个普通类、接口或枚举,可以有,也可以没有
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值