Author: See mountain link: juejin.cn/post/703079…

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

If you have used IDEA before, by default, when importing a class through import reaches the specified number of classes (5 classes and 3 static variables), the import mode is changed to on demand, that is, the import mode is folded with asterisks.

Colleagues suggest using single-type-import instead of on-demand import. I think since IDEA is a universal IDE, there will be no mistakes in this area, so I want to continue to follow the default configuration of IDEA.

So to summarize the differences between these two approaches. If you are not familiar with Java import, take a look here.

Two import declarations for import

There are two ways to import a class in Java:

  • Single-type-import, for exampleimport java.io.FileIt’s easy to understand and it’s the way we use it most of the time. Import them by explicitly specifying the class and interface paths.
  • Type-import-on-demand, for exampleimport java.io.*: Passes the wildcard*Define how to import, but instead of directly importing all classes in the package, you can import all classes. That is, import if you need it and don’t import if you don’t need it.

It has the following attributes:

  1. Java imports either package in one of two wayspublic(Only public classes and interfaces can be imported)
  2. I said that import declarations only import classes under the declaration directory, not subpackages, which is why they are called type import declarations.
  3. The simple name of the imported class or interface has compilation unit scope. This means that the type shorthand can be used anywhere in the compilation unit where the import statement resides. This does not mean that you can use the abbreviations of all members of the type, only the abbreviations of the type itself. For example, public classes in the java.lang package are automatically imported, includingMathandSystemClass. However, you cannot use the short names of their membersPI()andgc(), and must be usedMath.PI()andSystem.gc().What you don’t need to type isjava.lang.Math.PI()andjava.lang.System.gc().
  4. Programmers sometimes import the current package orjava.langPackage, which is not needed because the members of the current package are themselves in scope, whilejava.langPackages are automatically imported. The Java compiler ignores these redundant import declarations.

Import mechanisms on demand

On-demand type imports are easier to use in most cases; a single wildcard can import all the classes in a package without having to write a bunch of imports.

However, according to the conservation of energy, the energy saved when typing code must be expended elsewhere.

The Date class, for example, could be written as import java.util.* if it uses on-demand type imports entirely. The compiler does not know if the Date class should use the java.util package or the java.sql class when the statement is prepared. Reference to ‘Date’ is ambiguous, both ‘java.util.Date’ and ‘java.sql.Date’ match

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

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

  1. Compile speed: Because of the nature of the on-demand import mechanism, all classes that match the package name need to be found in the CLASSPATH, which consumes performance at compile time. In small projects, this speed is negligible. If you’re in a big project, there are detailed differences.
  2. Readability: In IDE development, we rarely use theimportTo view the path of the class. But if we need to edit files in other environments, like Vim, fromimportIt is convenient to look at the path of the class.

What happens when you import classes that you don’t need

Rationally, the Java compiler will optimize this by not adding unnecessary import declarations to the class file, but I didn’t see where that was, so try this:

Define the Java class first:

package cn.howardliu; // Import java.util.Date; // Import java.util. // The required type import import java.math.*; / / no need to use the single type of import import Java. SQL PreparedStatement; // Unneeded on-demand type import java.awt.*; public class Main { private Date date1; private BigDecimal num1; public void test(){ Date date2 = new Date(); BigDecimal num2 = new BigDecimal(0); }} Copy the codeCopy the code

Javap-verbose main. class to view the compilation result:

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. JavaCopy the code

The class file contains:

  1. On-demand type imports are represented in a class file in the same way as by type imports, where the required class imports are found and not all classes in the package are imported.

  2. Unnecessary class import declarations will eventually be optimized out of the class file.

  3. An import in Java, unlike an include in C, does not write the declared class to a class file, which is still a separate class file.

Which method is recommended by the JDK

The JDK is definitely the benchmark for Java programming, and many of us can learn from it:

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; Copy the codeCopy the code

This is the import declaration in java.util.properties, and as you can see, the single-type import declaration is used, so we’ll stick with single-type imports if we don’t have any other requirements.

Today to share a system of Java books, suitable for small white to god of all kinds of needs are sorted out.

                                                                              

Click here: Java Details pack

At the end of the article think

  1. The JavaimportIs a class import declaration that does not write files to the compiled class file
  2. The JavaimportThere are two import modes: single-type import and on-demand type import
  3. On-demand type imports incur a performance penalty only during compilation and are indistinguishable from single-type imports at run time
  4. Most of the JDK source code uses single-type imports.