When java import imports a package, what should we pay attention to?

java import import package

Hello, I am watching the mountains.

The reason for this article is a disagreement with my colleagues about the import statement during the code review.

Those who have used IDEA know that by default, when importing classes through import, when the number reaches the set number (5 classes, 3 static variables), it will be changed to the on-demand import method, that is, use the * sign to fold the import .

Colleagues suggest not to use on-demand import, but to use single-type-import. And I think that since IDEA is a universe-level IDE, there will be no mistakes in this kind of place, so I want to continue to follow the IDEA default configuration.

So sum up the differences between these two methods. If you are not familiar with java import, from here take a look.

Two import declarations of import

In java, there are two ways to import classes through import:

  • Single-type-import (single-type-import), for example import java.io.File: This method is easier to understand, and most of the time we use this method. Import them in by clearly specifying the class and interface path.
  • Type-import-on-demand (type-import-on-demand), for example import java.io.*, *defines the import method through wildcards , but not all classes in this package are directly imported, but all classes can be imported. In other words, if you need to import it, you don't need to import it.

Has the following attributes:

  1. Java imports publicthe classes and interfaces of any one of the packages in these two ways (only public classes and interfaces can be imported)
  2. As mentioned above, import declarations only import classes under the declaration directory and not subpackages, which is why they are called type import declarations.
  3. The simple name of the imported class or interface has the scope of the compilation unit. This means that the short name of the type can be used anywhere in the compilation unit where the import statement is located. This does not mean that you can use the short names of all members of the type, but only the short names of the type itself. For example: the public classes in the java.lang package are automatically imported, including Mathand Systemclasses. However, you cannot use the PI()sum of the short names of their members gc(), but must use the Math.PI()sum System.gc(). You do not need to type the java.lang.Math.PI()sum java.lang.System.gc().
  4. Programmers sometimes import the current package or java.langpackage, which is unnecessary, because the members of the current package themselves are in scope, and the java.langpackage is automatically imported. The java compiler ignores these redundant import declarations.

Import mechanism on demand

On-demand type import is more convenient in most cases. A wildcard can import all classes under the package, so you don't have to write a lot of imports.

However, according to the conservation of energy, the energy saved when typing codes will inevitably be consumed elsewhere.

For example, a Dateclass can be written if it is completely imported using the on-demand type import java.util.*. When this class happens to be needed, an import PrepareStatementneeds to be added import java.sql.*. At this time, the compiler does not know whether the Dateclass is to be used in the java.utilpackage or java.sqlinside, it will report an Reference to 'Date' is ambiguous, both 'java.util.Date' and 'java.sql.Date' matchexception, which is the so-called naming conflict .

The solution is to specify Datethe full path to the class, that is, using a single type of import: import java.util.Date.

In addition to naming conflicts, there are some less obvious disadvantages:

  1. Compilation speed: Because of the characteristics of the on-demand import mechanism, you need to find all classes that match the package name under the CLASSPATH, which will consume performance during compilation. In small projects, this speed can be ignored. If in a large project, there will be detailed differences.
  2. Readability: In the development process using IDE, we rarely look at importthe path of the class. But if we need to edit files in other environments, such as vim, importit is very convenient to view the path of the class.

What happens when importing unnecessary classes

From a rational point of view, the java compiler will definitely optimize here, and will not add unnecessary import declarations to the class file, but I haven't seen any instructions before, so let's do some experiments:

First define the java class:

package cn.howardliu;

// 需要用到的单类型导入
import java.util.Date;
// 需要用到的按需类型导入
import java.math.*;
// 不需要用到的单类型导入
import java.sql.PreparedStatement;
// 不需要用到的按需类型导入
import java.awt.*;

public class Main {
    
    
    private Date date1;
    private BigDecimal num1;

    public void test(){
    
    
        Date date2 = new Date();
        BigDecimal num2 = new BigDecimal(0);
    }
}

javac Main.javaCompile by command , and then javap -verbose Main.classview the results of the compilation:

Classfile /path/to/Main.class
  Last modified 2021-1-31; size 439 bytes
  MD5 checksum 81e13559f738197b4875c2c2afd6fc41
  Compiled from "Main.java"
public class cn.howardliu.Main
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #7.#19         // java/lang/Object."<init>":()V
   #2 = Class              #20            // java/util/Date
   #3 = Methodref          #2.#19         // java/util/Date."<init>":()V
   #4 = Class              #21            // java/math/BigDecimal
   #5 = Methodref          #4.#22         // java/math/BigDecimal."<init>":(I)V
   #6 = Class              #23            // cn/howardliu/Main
   #7 = Class              #24            // java/lang/Object
   #8 = Utf8               date1
   #9 = Utf8               Ljava/util/Date;
  #10 = Utf8               num1
  #11 = Utf8               Ljava/math/BigDecimal;
  #12 = Utf8               <init>
  #13 = Utf8               ()V
  #14 = Utf8               Code
  #15 = Utf8               LineNumberTable
  #16 = Utf8               test
  #17 = Utf8               SourceFile
  #18 = Utf8               Main.java
  #19 = NameAndType        #12:#13        // "<init>":()V
  #20 = Utf8               java/util/Date
  #21 = Utf8               java/math/BigDecimal
  #22 = NameAndType        #12:#25        // "<init>":(I)V
  #23 = Utf8               cn/howardliu/Main
  #24 = Utf8               java/lang/Object
  #25 = Utf8               (I)V
{
  public cn.howardliu.Main();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 12: 0

  public void test();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=3, args_size=1
         0: new           #2                  // class java/util/Date
         3: dup
         4: invokespecial #3                  // Method java/util/Date."<init>":()V
         7: astore_1
         8: new           #4                  // class java/math/BigDecimal
        11: dup
        12: iconst_0
        13: invokespecial #5                  // Method java/math/BigDecimal."<init>":(I)V
        16: astore_2
        17: return
      LineNumberTable:
        line 17: 0
        line 18: 8
        line 19: 17
}
SourceFile: "Main.java"

It can be seen from the content of the class file:

  1. The presentation of the on-demand type import method in the class file is the same as the import by type. The required class import will be found, and all the classes in the package will not be imported.
  2. Unnecessary class import declarations will eventually be optimized away and will not appear in the class file.
  3. importUnlike the C language, Java includedoes not write the imported declared classes into the class file, and each is an independent class file.

JDK recommends which way

JDK is definitely the benchmark for java programming. Many of us can learn from JDK:

import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.security.AccessController;
import java.security.PrivilegedAction;

import sun.util.spi.XmlPropertiesProvider;

This is java.util.Propertiesthe import statement in. It can be seen that a single-type import statement is used. Therefore, if there are no other requirements, we try to use single-type import as much as possible.

End-of-sentence thinking

  1. Java importis a class import declaration, and will not write the file to the compiled class file
  2. importThere are two import methods for java : single type import and on-demand type import
  3. On-demand type import will only have performance loss during the compilation process, and there is no difference between single-type import at runtime
  4. Most of the JDK source code uses single-type imports.

Hello, I’m Kanshan, public account: Kanshan’s Lodge, a 10-year-old backend, open source contributors to Apache Storm, WxJava, and Cynomys. Main job: programmer, part-time job: architect. Swim in the code world, enjoy life in drama.

Personal homepage: https://www.howardliu.cn
Personal blog post: java import import package
CSDN homepage: http://blog.csdn.net/liuxinghao
CSDN blog post: java import import package

Public number: Watching the mountain hut

Guess you like

Origin blog.csdn.net/conansix/article/details/113487825