Java import 详解

Java import 详解

1. package 机制

Java 的 package 机制类似于 C++ 的 namespace 机制

在编写 Java 程序时,随着程序架构越来越大,类的个数也越来越多,这时就会发现管理程序中维护类名称也是一件很麻烦的事,尤其是一些同名问题的发生。有时,开发人员还可能需要将处理同一方面的问题的类放在同一个目录下,以便于管理。

为了解决上述问题,Java 引入了包(package)机制,提供了类的多层命名空间,用于解决类的命名冲突,类文件管理等问题。

包允许将类组合成较小的单元(类似文件夹),它基本上隐藏了类,并避免了名称上的冲突。包允许在更广泛的范围内保护类,数据和方法。你可以在包内定义类,而在包外的代码不能访问该类。这使你的类相互之间有隐私,但不被其他世界所知。

2. 包名与类名

package 名称就像是我们的姓,而 class 名称就像是我们的名字 。packagepackage 的附属关系用 . 来连接,这就像是复姓。比如说 java.lang.String 就是复姓 java.lang,名字为 String 的类别,java.io.InputStream 则是复姓 Java.io 名字为 InputStream 的类别。

在 Java 程序文件中需要引用外部的类时需要指定被引用类所在的包名,可以使用 import 将类所在的包导入到当前文件,导入后使用外部类则不需要指定完整的包名。

3. 两种导入声明

Java 支持两种导入声明,分别为 单类型导入(single-type-import)按需类型导入(type-import-on-demand),注意只有声明为 public 类型的类和接口才能被导入。

单类型导入,这很好理解类似于 import java.io.File 这样,仅仅导入一个 public 类或者接口,我们在编写 Java 代码时一般习惯于这种方式。

按需类型导入,类似于 import java.io.* 这样,通过通配符 * 定义导入方式,在这里 * 号表示的意思是指定使用按需导入方式,不要误以为是导入了某个包下的所有类。这里需要注意了使用这种方式并不是直接将某个包下的所有类通通导入到当前文件中,而是视使用情况而定。换句话说就是将被使用到的类导入,未使用到的类不导入。

4. 按需导入分析

4.1 类目录定位

Java 编译器会从启动目录(bootstrap),扩展目录(extension)和用户类路径下去定位需要导入的类,但是这三种目录仅仅是需要被导入类的顶层目录。那么编译器是怎么得到类的位置的呢?答案是通过查找,知道顶层路径后通过查找顶层路径下可能的包,类,文件,最终可以得到若干条可能的绝对路径,绝对路径的样式大致如下:

绝对路径 = 顶层路径名(即启动目录或扩展目录再或者用户类目录) / 包名 / 文件名.class

4.2 查找机制

对于单类型导入很简单,因为包明和文件名都已经确定,所以可以一次性查找定位。对于按需类型导入则比较复杂,编译器会把包名和文件名进行排列组合,然后根据所有的可能性进行查找。

package com;

import java.io.*;
import java.util.*;

当你的类文件中用到了 File 类,我们很容易就知道 File 类位于 java.io 中,但是对于编译器来说它并不知道,所以它需要搜索所有可能出现 File 类的地方,那么可能出现 File 类的位置或目录有哪些呢?


File,如果 File 类属于无名包,就是说 File 类没有使用 package 语句声明,此时编译器会首先搜索无名包。

com.File,如果 File 类处于当前包中。

java.lang.File,编译器会自动导入的 java.lang 包,并搜索该包。

java.io.File, Java 的核心输入输出流 java.io 包。

java.util.File, Java 的实用工具类库。


以上就是可能出现 File 类的五个位置,需要注意的地方就是,编译器在找到 java.io.File 类之后并不会停止下一步的寻找,而是会把所有的可能性都查找完毕以确定是否有相同的类导入冲突。

假设此时的顶层路径有三个,那么编译器就会进行 3x5=15 次查找。

注意:如果在查找完成后,编译器发现了两个同名的类,那么就会产生报错。删除你不用的那个类,然后再次编译

4.3 结论

了解以上原理之后,我们可以得出这样的结论:按需类型导入是绝对不会降低 Java 代码的执行效率的,但会影响到 Java 代码的编译速度。

查看 JDK 的源代码就知道 SUN 的软件工程师一般不会使用按需类型导入。因为使用单类型导入至少有以下两点好处:

  • 提高编译速度。

  • 避免命名冲突。

  • 当然,使用单类型导入会使 import 语句较长。

5. 编译优化

不被使用的类的导入声明,最终都会被编译器优化去除,不会出现在 class 文件中。Java 中的 import 与 C 语言中的 include 不同(C 语言的 #include 会将被包含文件的内容复制并替换当前文件的 #include 语句),import 不会将导入声明的类写入到 class 文件中,而是各自依旧使用独立的 class 文件。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
@Import注解是Java中用于导入其他配置类或组件的注解,它可以用在类级别上,用于导入其他类或组件,从而让它们成为当前类的依赖项。@Import注解支持三种不同的导入方式: 1. 导入配置类: 可以使用@Import注解来导入一个或多个配置类,这些配置类会被Spring容器加载并且进行解析,从而可以在应用程序中使用。例如: ``` @Configuration @Import({Config1.class, Config2.class}) public class AppConfig { // Configuration code... } ``` 在上面的例子中,AppConfig类使用@Import注解来导入了Config1和Config2两个配置类。 2. 导入普通的组件: 除了导入配置类外,@Import注解还可以用来导入普通的组件,例如一个普通的Java类、接口或枚举。例如: ``` @Configuration @Import(MyComponent.class) public class AppConfig { // Configuration code... } ``` 在上面的例子中,AppConfig类使用@Import注解来导入了一个名为MyComponent的普通Java组件。 3. 导入ImportSelector: @Import注解还可以使用ImportSelector类型的实现类来动态地导入一组组件,这些组件可以根据不同的条件进行选择。例如: ``` @Configuration @Import(MyImportSelector.class) public class AppConfig { // Configuration code... } ``` 在上面的例子中,AppConfig类使用@Import注解来导入了一个名为MyImportSelector的ImportSelector实现类,它会根据不同的条件来选择一组组件,然后将它们动态导入到应用程序中。 总之,@Import注解是一个非常有用的注解,它可以帮助我们方便地导入其他配置类或组件,从而让我们的应用程序更加灵活和可扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值