龙空技术网

Python 的 import 跟 Java 的 import 有什么区别?

老吴与编程 101

前言:

现在看官们对“python动态导入与静态导入包”可能比较注重,看官们都想要分析一些“python动态导入与静态导入包”的相关文章。那么小编也在网上收集了一些关于“python动态导入与静态导入包””的相关知识,希望兄弟们能喜欢,看官们一起来了解一下吧!

你好,我是 shengjk1,多年大厂经验,努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注!你会有如下收益:

1. 了解大厂经验

1. 拥有和大厂相匹配的技术等

希望看什么,评论或者私信告诉我!

一、 前言

这一篇是上一篇 [关于 Python 的 import,你了解多少?]() 的姊妹篇。在上一篇中,我们详细论述了 Python import 关键字。本篇,将会详细比一下,两个特别有代表性的语言 Java 和 Python 中的 import 关键字同和异

二、不同点

两种语言的 import 的不同点有很多,比如:

1. 语法:Java和Python中的`import`语句的语法不同。在Java中,`import`语句通常以`import`关键字开始,后面跟着要导入的类或包的全限定名。而在Python中,`import`语句通常以`import`关键字开始,后面跟着要导入的模块的名称。

2. 编译时 vs 运行时:在Java中,`import`语句在编译时处理,编译器会解析导入路径、查找类文件并加载类。而在Python中,`import`语句在运行时处理,解释器会查找模块文件并执行其中的代码。

3. 名称冲突解决:在Java中,如果导入的类或包的名称与当前命名空间中的其他定义冲突,必须使用完整的类名或使用`import`语句的全限定名来区分。而在Python中,可以使用`as`关键字为导入的模块或对象指定别名,以避免名称冲突。

4. 静态绑定 vs 动态绑定:在Java中,类的导入是在编译时进行的,编译器会根据导入的类的类型进行静态绑定。而在Python中,模块的导入是在运行时进行的,解释器会根据导入的模块的名称进行动态绑定。

其他的很容易理解,这里我们重点对 第 2 和 3 条进行详细描述

2.1 import module or class2.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 package2.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`语句时,它执行以下几个步骤:

1. **解析导入路径**:解释器会解析`import`语句中指定的模块的路径。这个路径可以是相对路径或绝对路径,并且可以包含多个层级和包名。

2. **查找模块**:解释器会根据解析的路径查找对应的模块文件(以 `.py` 或 `.pyc` 形式存在)。它会按照一定的搜索顺序查找模块,包括当前目录、Python标准库目录和自定义模块路径等。

3. **编译模块**:一旦找到模块文件,解释器会对模块进行编译,将其转换为字节码形式。对于首次导入的模块,解释器会生成对应的 `.pyc` 文件,以便提高后续导入的性能。

4. **创建命名空间**:解释器会为导入的模块创建一个独立的命名空间,用于存储模块中定义的变量、函数和类等。这样可以避免命名冲突,并允许代码通过模块名来引用其中的对象。

5. **执行模块代码**:解释器会执行模块中的代码,按照顺序执行模块中的语句和定义的函数、类等。这样,模块中的变量和函数会被加载到命名空间中,可以在代码中直接访问和使用。

6. **返回模块对象**:当模块中的代码执行完毕后,解释器会返回一个代表该模块的模块对象。这个模块对象可以被赋值给变量,以便在代码中使用模块中的功能。

需要注意的是,Python解释器在首次导入模块时,会执行模块中的代码并创建对应的命名空间。但在后续的导入过程中,解释器会直接使用已经编译和加载的模块对象,而不会再次执行模块中的代码。

总结起来,Python解释器在遇到`import`语句时会解析导入路径,查找并编译模块,创建命名空间,并执行模块中的代码。这样,模块中的变量、函数和类等会被加载到命名空间中,可以在代码中直接访问和使用。

3.2 Java

在Java中,`import`语句的作用是引入其他类或包,以便在代码中使用这些类或包中定义的功能。当Java解释器遇到`import`语句时,它会执行以下几个步骤:

1. **解析import语句:** Java解释器会解析`import`语句,获取导入的类或包的名称。例如,`import java.util.ArrayList;`将导入`java.util`包中的`ArrayList`类。

2. **查找类或包:** 解释器会查找导入的类或包,以确定其位置。它首先搜索Java类路径(包括标准库和自定义库),然后在指定位置查找。如果找到了类或包,解释器将继续执行下一步。否则,将会抛出`ClassNotFoundException`或`NoClassDefFoundError`等异常。

3. **加载类或包:** 如果找到了类或包,解释器将加载它们,同时也会**创建相应的命名空间**。加载过程包括加载字节码文件、验证字节码的正确性以及将字节码转换为内存中的可执行代码。如果导入的是一个包,解释器将加载包中的所有类。

4. **建立符号引用:** 解释器建立与导入的类或包的符号引用,以便在代码中引用它们。这允许你使用导入的类或包的名称而不必使用完全限定的类名。

5. **解析符号引用:** 当你在代码中使用导入的类或包时,解释器会解析符号引用,以确定它们的具体含义。例如,如果你在代码中使用`ArrayList`,解释器会解析它为导入的`java.util.ArrayList`类。

需要注意的是,`import`语句本身并不会导致类的加载或执行,它只是告诉解释器需要访问某个类或包。类的加载和初始化是在实际使用该类时按需发生的,如创建对象、调用方法等。

一旦类被加载和初始化,JVM会缓存该类的Class对象,以便后续的使用。这样,在多次使用同一个类时,解释器不需要重新加载和初始化,而是直接使用缓存的Class对象。

三、相同点

1. 功能:无论是 Java 还是 Python ,`import`语句的主要功能都是引入其他类或模块,以便在代码中使用它们的功能。

2. 命名空间:`import`语句将被导入的类或模块的定义引入到当前命名空间中,以便在代码中直接访问它们。

3. 都是 关键字

四、总结

Python和Java作为流行的编程语言,都提供了import机制来引入外部代码模块/类。尽管在具体语法、导入时机、执行细节等方面有一定区别,但二者的import语句都具有引入外部代码、扩展功能、统一命名空间的作用,可以增强代码的模块化和可重用性。掌握import的用法对于合理组织和复用代码至关重要。

标签: #python动态导入与静态导入包