你好,我是 shengjk1,多年大厂经验,努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注!你会有如下收益:
- 了解大厂经验
- 拥有和大厂相匹配的技术等
希望看什么,评论或者私信告诉我!
一、 前言
这一篇是上一篇 关于 Python 的 import,你了解多少? 的姊妹篇。在上一篇中,我们详细论述了 Python import 关键字。本篇,将会详细比一下,两个特别有代表性的语言 Java 和 Python 中的 import 关键字同和异
二、不同点
两种语言的 import 的不同点有很多,比如:
-
语法:Java和Python中的
import
语句的语法不同。在Java中,import
语句通常以import
关键字开始,后面跟着要导入的类或包的全限定名。而在Python中,import
语句通常以import
关键字开始,后面跟着要导入的模块的名称。 -
编译时 vs 运行时:在Java中,
import
语句在编译时处理,编译器会解析导入路径、查找类文件并加载类。而在Python中,import
语句在运行时处理,解释器会查找模块文件并执行其中的代码。 -
名称冲突解决:在Java中,如果导入的类或包的名称与当前命名空间中的其他定义冲突,必须使用完整的类名或使用
import
语句的全限定名来区分。而在Python中,可以使用as
关键字为导入的模块或对象指定别名,以避免名称冲突。 -
静态绑定 vs 动态绑定:在Java中,类的导入是在编译时进行的,编译器会根据导入的类的类型进行静态绑定。而在Python中,模块的导入是在运行时进行的,解释器会根据导入的模块的名称进行动态绑定。
其他的很容易理解,这里我们重点对 第 2 和 3 条进行详细描述
2.1 import module or class
2.1.1 Python import module
在Python中,当一个模块被导入时,模块中的代码会被执行。然而,模块中的代码只会在第一次导入时执行一次。之后,如果再次导入同一个模块,Python解释器会直接使用已经加载的模块,而不会再次执行模块中的代码。
值得注意的是,如果在模块中存在全局级别的可执行语句(例如函数定义以外的代码),则在导入时会执行这些语句。因此,模块的导入可能会触发一些副作用操作,例如打印输出或初始化全局变量。
2.1.2 Java import class
在Java中,当一个类被导入时,该类的代码不会被立即执行。类的执行是在实际使用该类的时候发生的。
当导入一个类时,Java编译器会在编译阶段检查类的语法和类型,并生成或获取对应的字节码文件。这个字节码文件包含了类的定义和方法的字节码指令,但不会立即执行。
在程序运行时,当使用该类创建对象、调用方法或访问静态成员时,Java虚拟机(JVM)会加载该类的字节码文件,并根据需要执行类的代码。
需要注意的是,类的加载和初始化是按需进行的,即当第一次使用某个类时才会发生。一旦类被加载和初始化,JVM会缓存该类的Class对象,以便后续的使用。这种机制可以提高类的加载和执行的性能。
例如,假设我们有一个名为MyClass
的类,并将其导入到另一个类中:
import com.example.MyClass;
public class AnotherClass {
public static void main(String[] args) {
System.out.println("Before creating an instance of MyClass");
MyClass obj = new MyClass(); // 创建MyClass的实例
System.out.println("After creating an instance of MyClass");
obj.someMethod(); // 调用MyClass的方法
}
}
在上述代码中,当AnotherClass
被执行时,会先打印Before creating an instance of MyClass
,然后创建MyClass
的实例,并打印After creating an instance of MyClass
。这时,MyClass
的构造函数会被调用。
如果MyClass
中有其他静态成员或静态初始化块,它们也会在类被加载时执行一次。
总结起来,当一个Java类被导入时,类的代码不会立即执行。类的加载和初始化是在实际使用该类的时候按需发生的。类的加载和执行是由Java虚拟机(JVM)在程序运行时控制的。
2.2 import package
2.2.1 Python import package
在Python中,当导入一个包(package)时,包本身不会被执行。只有在使用该包中的模块或对象时,才会执行相应的代码。
当导入一个包时,Python解释器会查找并执行该包下的__init__.py
文件。__init__.py
文件可以包含一些初始化代码,用于设置包的环境、导入子模块或执行其他需要在导入时执行的操作。但这些代码只会在首次导入包时执行一次。
2.2.2 Java import package
在Java中,当一个包(package)被导入后,并不会立即加载和执行其中的类。类的加载和执行是在实际使用该类时进行的。
具体来说,当使用一个类时(例如创建该类的实例、调用该类的静态方法、访问该类的静态字段等),Java虚拟机(JVM)会根据需要进行类的加载和初始化操作。类的加载是指将类的字节码加载到内存中,并创建对应的Class对象。类的初始化是指执行类的静态初始化器和静态变量的赋值操作。
类的加载和初始化是按需进行的,即当第一次使用某个类时才会发生。一旦类被加载和初始化,JVM会缓存该类的Class对象,以便后续的使用。
需要注意的是,Java的类加载是按需延迟的,即在类被首次使用之前,它的加载和初始化都不会发生。这种延迟加载的机制可以提高性能,避免不必要的类加载和初始化操作。
3. import 时各自的解释器/编译器在做什么( 只是一个大概的过程,并不是严格正确,主要是为了方便理解 )
3.1 Python
在Python中,当解释器遇到import
语句时,它执行以下几个步骤:
-
解析导入路径:解释器会解析
import
语句中指定的模块的路径。这个路径可以是相对路径或绝对路径,并且可以包含多个层级和包名。 -
查找模块:解释器会根据解析的路径查找对应的模块文件(以
.py
或.pyc
形式存在)。它会按照一定的搜索顺序查找模块,包括当前目录、Python标准库目录和自定义模块路径等。 -
编译模块:一旦找到模块文件,解释器会对模块进行编译,将其转换为字节码形式。对于首次导入的模块,解释器会生成对应的
.pyc
文件,以便提高后续导入的性能。 -
创建命名空间:解释器会为导入的模块创建一个独立的命名空间,用于存储模块中定义的变量、函数和类等。这样可以避免命名冲突,并允许代码通过模块名来引用其中的对象。
-
执行模块代码:解释器会执行模块中的代码,按照顺序执行模块中的语句和定义的函数、类等。这样,模块中的变量和函数会被加载到命名空间中,可以在代码中直接访问和使用。
-
返回模块对象:当模块中的代码执行完毕后,解释器会返回一个代表该模块的模块对象。这个模块对象可以被赋值给变量,以便在代码中使用模块中的功能。
需要注意的是,Python解释器在首次导入模块时,会执行模块中的代码并创建对应的命名空间。但在后续的导入过程中,解释器会直接使用已经编译和加载的模块对象,而不会再次执行模块中的代码。
总结起来,Python解释器在遇到import
语句时会解析导入路径,查找并编译模块,创建命名空间,并执行模块中的代码。这样,模块中的变量、函数和类等会被加载到命名空间中,可以在代码中直接访问和使用。
3.2 Java
在Java中,import
语句的作用是引入其他类或包,以便在代码中使用这些类或包中定义的功能。当Java解释器遇到import
语句时,它会执行以下几个步骤:
-
解析import语句: Java解释器会解析
import
语句,获取导入的类或包的名称。例如,import java.util.ArrayList;
将导入java.util
包中的ArrayList
类。 -
查找类或包: 解释器会查找导入的类或包,以确定其位置。它首先搜索Java类路径(包括标准库和自定义库),然后在指定位置查找。如果找到了类或包,解释器将继续执行下一步。否则,将会抛出
ClassNotFoundException
或NoClassDefFoundError
等异常。 - 加载类或包: 如果找到了类或包,解释器将加载它们,同时也会创建相应的命名空间。加载过程包括加载字节码文件、验证字节码的正确性以及将字节码转换为内存中的可执行代码。如果导入的是一个包,解释器将加载包中的所有类。
- 建立符号引用: 解释器建立与导入的类或包的符号引用,以便在代码中引用它们。这允许你使用导入的类或包的名称而不必使用完全限定的类名。
-
解析符号引用: 当你在代码中使用导入的类或包时,解释器会解析符号引用,以确定它们的具体含义。例如,如果你在代码中使用
ArrayList
,解释器会解析它为导入的java.util.ArrayList
类。
需要注意的是,import
语句本身并不会导致类的加载或执行,它只是告诉解释器需要访问某个类或包。类的加载和初始化是在实际使用该类时按需发生的,如创建对象、调用方法等。
一旦类被加载和初始化,JVM会缓存该类的Class对象,以便后续的使用。这样,在多次使用同一个类时,解释器不需要重新加载和初始化,而是直接使用缓存的Class对象。
三、相同点
- 功能:无论是 Java 还是 Python ,
import
语句的主要功能都是引入其他类或模块,以便在代码中使用它们的功能。 - 命名空间:
import
语句将被导入的类或模块的定义引入到当前命名空间中,以便在代码中直接访问它们。 - 都是 关键字
四、总结
Python和Java作为流行的编程语言,都提供了import机制来引入外部代码模块/类。尽管在具体语法、导入时机、执行细节等方面有一定区别,但二者的import语句都具有引入外部代码、扩展功能、统一命名空间的作用,可以增强代码的模块化和可重用性。掌握import的用法对于合理组织和复用代码至关重要。
网友评论