こんにちは、私は山を見ています。
この記事の理由は、コードレビュー中のインポートステートメントに関する同僚との意見の相違です。
IDEAを使用したことのある人は、デフォルトで、インポートを介してクラスをインポートするときに、その数が設定された数(5クラス、3静的変数)に達すると、オンデマンドインポート方式に変更されることを知っています。つまり、*を使用します。インポートを折りたたむための署名。
同僚は、オンデマンドインポートを使用するのではなく、シングルタイプインポートを使用することを提案しています。そして、IDEAはユニバースレベルのIDEなので、このような場所で間違いはないと思いますので、引き続きIDEAのデフォルト設定に従いたいと思います。
したがって、これら2つの方法の違いを要約してください。Javaインポートに慣れていない場合は、ここから見てください。
輸入の2つの輸入宣言
Javaでは、インポートを介してクラスをインポートする方法は2つあります。
- 単一タイプのインポート(単一タイプのインポート)の例
import java.io.File
:この方法は理解しやすく、ほとんどの場合、この方法を使用します。クラスとインターフェイスパスを明確に指定して、それらをインポートします。 - たとえば
import java.io.*
、Type-import-on-demand(type-import-on-demand)は、ワイルドカードを使用*
してインポート方法を定義しますが、このパッケージのすべてのクラスが直接インポートされるわけではありませんが、すべてのクラスをインポートできます。つまり、インポートする必要がある場合、不要な場合はインポートしないでください。
次の属性があります。
- Javaは
public
、これら2つの方法でパッケージのいずれかのクラスとインターフェイスをインポートします(パブリッククラスとインターフェイスのみをインポートできます) - 上記のように、インポート宣言は、宣言ディレクトリの下のクラスのみをインポートし、サブパッケージはインポートしません。そのため、これらはタイプインポート宣言と呼ばれます。
- インポートされたクラスまたはインターフェースの単純な名前には、コンパイル単位のスコープがあります。これは、タイプの短い名前が、importステートメントが配置されているコンパイル単位のどこでも使用できることを意味します。これは、型のすべてのメンバーの短縮名を使用できることを意味するのではなく、型自体の短縮名のみを使用できることを意味します。例:java.langパッケージ内のパブリッククラスは自動的に含めて、インポートされ
Math
およびSystem
クラス。ただし、使用することはできませんPI()
総和そのメンバーの短い名前のをgc()
、しかし使用する必要がありますMath.PI()
合計をSystem.gc()
。あなたが入力する必要はありませんjava.lang.Math.PI()
合計をjava.lang.System.gc()
。 - プログラマー
java.lang
は、現在のパッケージのメンバー自体がスコープ内にあり、java.lang
パッケージが自動的にインポートされるため、現在のパッケージまたはパッケージをインポートすることがありますが、これは不要です。Javaコンパイラは、これらの冗長なインポート宣言を無視します。
オンデマンドのインポートメカニズム
ほとんどの場合、オンデマンドタイプのインポートの方が便利です。ワイルドカードを使用すると、パッケージ内のすべてのクラスをインポートできるため、多くのインポートを作成する必要はありません。
しかし、エネルギー保存の法則によれば、コードを入力するときに節約されたエネルギーは、必然的に他の場所で消費されます。
たとえば、Date
オンデマンドタイプを使用して完全にインポートされた場合、クラスを作成できますimport java.util.*
。このクラスが必要になった場合は、インポートPrepareStatement
を追加する必要がありますimport java.sql.*
。この時点で、コンパイラはDate
クラスがjava.util
パッケージjava.sql
内で使用されるのか内部で使用されるのかわからないReference to 'Date' is ambiguous, both 'java.util.Date' and 'java.sql.Date' match
ため、いわゆるネーミングと呼ばれる例外を報告します。競合。
解決策はDate
、クラスへのフルパスを指定することです。つまり、単一のタイプのインポートを使用しますimport java.util.Date
。
名前の競合に加えて、あまり明白ではない欠点がいくつかあります。
- コンパイル速度:オンデマンドインポートメカニズムの特性により、CLASSPATHの下のパッケージ名に一致するすべてのクラスを見つける必要があります。これにより、コンパイル中にパフォーマンスが低下します。小さなプロジェクトでは、この速度は無視できます。大規模なプロジェクトの場合、詳細な違いがあります。
- 読みやすさ:IDEを使用した開発プロセス
import
では、クラスのパスを確認することはめったにありません。ただし、vimなどの他の環境でファイルを編集する必要がある場合はimport
、クラスのパスを表示すると非常に便利です。
不要なクラスをインポートするとどうなりますか
合理的な観点から、Javaコンパイラはここで確実に最適化し、クラスファイルに不要なインポート宣言を追加しませんが、これまでに命令を見たことがないので、いくつかの実験を行いましょう。
まず、Javaクラスを定義します。
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.java
でコンパイルしてjavap -verbose Main.class
から、コンパイルの結果を表示します。
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"
これは、クラスファイルの内容から確認できます。
- クラスファイルでのオンデマンドタイプインポートメソッドの表示は、タイプ別インポートと同じです。必要なクラスインポートが見つかり、パッケージ内のすべてのクラスがインポートされるわけではありません。
- 不要なクラスインポート宣言は最終的に最適化され、クラスファイルには表示されません。
import
C言語とは異なり、Javainclude
はインポートされた宣言済みクラスをクラスファイルに書き込みません。それぞれが独立したクラスファイルです。
JDKはどちらの方法を推奨します
JDKは間違いなくJavaプログラミングのベンチマークです。私たちの多くは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;
これはjava.util.Properties
のインポートステートメントです。単一タイプのインポートステートメントが使用されていることがわかります。したがって、他の要件がない場合は、可能な限り単一タイプのインポートを使用するようにしています。
文末思考
- Java
import
はクラスインポート宣言であり、コンパイルされたクラスファイルにファイルを書き込みません。 - Javaには、
import
シングルタイプのインポートとオンデマンドタイプのインポートの2つのインポート方法があります。 - オンデマンドタイプのインポートでは、コンパイルプロセス中にのみパフォーマンスが低下し、実行時のシングルタイプのインポートに違いはありません。
- ほとんどのJDKソースコードは単一タイプのインポートを使用します。
こんにちは、私はKanshanです。パブリックアカウント:Kanshan’s Lodge、10歳のバックエンド、Apache Storm、WxJava、Cynomysのオープンソース寄稿者。主な仕事:プログラマー、アルバイト:建築家。コードの世界で泳ぎ、ドラマでの生活を楽しんでください。
個人のホームページ:https
://www.howardliu.cn個人のブログ投稿:java import import package
CSDNホームページ:http:
//blog.csdn.net/liuxinghao CSDNブログ投稿:java import import package