java中import詳解
前言
import與package機制相關,這裡先從package入手,再講述import以及static import的作用。
package
package名稱就像是我們的姓,而class名稱就像是我們的名字 。package和package的附屬關係用”.”來連線,這就像是複姓。比如說 java.lang.String就是複姓 java.lang,名字為 String 的類別;java.io.InputStream 則是複姓 java.io,名字為 InputStream的類別。
import
import就是在java檔案開頭的地方,先說明會用到那些類別。
接著我們就能在程式碼中只用類名指定某個類,也就是隻稱呼名字,不稱呼他的姓。
首先,在程式開頭寫:
import java.lang.System;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
於是我們就可以在程式中這樣寫到:
InputStream = System.in; InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr);
一個java檔案就像一個大房間,我們在門口寫著在房間裡面的class的姓和名字,所以在房間裡面提到某個class就直接用他的名字就可以。例如:
System 就是指 java.lang.System,而 InputStream 就是指 java.io.InputStream。
但是如果一個java檔案裡面有多個同個“姓”,即包名相同的類(例如上面的InputStream,InputStreamReader,BufferedReader都是java.io中的類),我們一一寫出顯得比較繁雜,所以Sun就讓我們可以使用
1 import java.lang.*; 2 import java.io.*;
表示檔案裡面說到的類不是java.lang包的就是java.io包的。編譯器會幫我們選擇與類名對應的包。
但是我們不可以寫成:
1 import java.*;
因為那些類別是姓 java.io 而不是姓 java。就像姓『諸葛』的人應該不會喜歡你稱他為『諸』 先生吧。
這樣寫的話只會將java包下的類宣告,而不不會宣告子包的任何類。
這裡注意,java.lang包裡面的類實在是太常太常太常用到了,幾乎沒有類不用它的, 所以不管你有沒有寫 import java.lang,編譯器都會自動幫你補上,也就是說編譯器只要看到沒有姓的類別,它就會自動去lang包裡面查詢。所以我們就不用特別去 import java.lang了。
import的兩種匯入宣告
- 單型別匯入(single-type-import)
(例:import java.util.ArrayList; ) - 按需型別匯入(type-import-on-demand)
(例:import java.util.*;)
static import靜態匯入
static import和import其中一個不一致的地方就是static import匯入的是靜態成員,而import匯入的是類或介面型別。
例項:
如下是一個有靜態變數和靜態方法的類
1 package com.assignment.test; 2 3 public class staticFieldsClass { 4 static int staticNoPublicField = 0; 5 public static int staticField = 1; 6 public static void staticFunction(){} 7 }
平時我們使用這些靜態成員是用類名.靜態成員的形式使用,即staticFieldsClass.staticField或者staticFieldsClass.staticFunction()。
現在用static import的方式:
1 //**精準匯入** 2 //直接匯入具體的靜態變數、常量、方法方法,注意匯入方法直接寫方法名不需要括號。 3 import static com.assignment.test.StaticFieldsClass.staticField; 4 import static com.assignment.test.StaticFieldsClass.staticFunction; 5 6 //或者使用如下形式: 7 //**按需匯入**不必逐一指出靜態成員名稱的匯入方式 8 //import static com.assignment.test.StaticFieldsClass.*; 9 10 public class StaticTest { 11 public static void main(String[] args) { 12 //這裡直接寫靜態成員而不需要通過類名呼叫 13 System.out.println(staticField); 14 staticFunction(); 15 } 16 }
按需匯入機制
使用按需匯入宣告是否會降低Java程式碼的執行效率?
絕對不會!
一、import的按需匯入
mport java.util.*; public class NeedImportTest { public static void main(String[] args) { ArrayList tList = new ArrayList(); } }
編譯之後的class檔案 :
//import java.util.*被替換成import java.util.ArrayList
//即按需匯入編譯過程會替換成單型別匯入。
import java.util.ArrayList;
public class NeedImportTest {
public static void main(String[] args) {
new ArrayList();
}
}
這是否意味著你總是可以使用按需匯入宣告?
是,也不是!
在類似Demo的非正式開發中使用按需匯入宣告顯得很有用。
然而,有這四個理由讓你可以放棄這種宣告:
編譯速度:在一個很大的專案中,它們會極大的影響編譯速度.但在小型專案中使用在編譯時間上可以忽略不計。
命名衝突:解決避免命名衝突問題的答案就是使用全名。而按需匯入恰恰就是使用匯入宣告初衷的否定。
說明問題:畢竟高階語言的程式碼是給人看的,按需匯入看不出使用到的具體型別。
無名包問題:如果在編譯單元的頂部沒有包宣告,Java編譯器首選會從無名包中搜索一個型別,然後才是按需型別宣告。如果有命名衝突就會產生問題。