2011-03-15 38 views
8

最近我聽到過像「你永遠不應該使用通配符導入」的說法。所以我想問這個社區。在Java生產代碼中,通配符導入是否真的永遠不會被使用,不管是什麼?這個規則是否有例外?我對你的個人經歷和觀點感興趣。你在生產代碼中使用它們,你會把它推薦給其他人嗎?你如何使用它們 - 你能推薦最好的方法嗎?通配符導入Java和Scala中的用法

從Scala的角度來看它也很有趣。這同樣適用於Scala嗎? Scala中的通配符導入應該僅用於演示文稿幻燈片和SO答案中?

如果你會看scalaz page,例如,他們建議像通配符進口的用法:

import scalaz._ 
import Scalaz._ 

我想這也是很重要的考慮通常與通配符進口隱式轉換。

+20

你不應該聽從以「你永遠不應該」開頭的建議。 – musiKk 2011-03-15 11:39:31

+0

@musiKk:我試着:)但如果你經常聽到它,你開始喲懷疑自己... – tenshi 2011-03-15 11:45:09

+0

@musiKk,你永遠不應該聽從以「你永遠不應該......太頻繁」開頭的建議;) – 2011-03-15 11:46:07

回答

12

在Scala中,通配符導入是必須的,因爲許多庫期望它們的隱式轉換在範圍內,但它們並不總是方便的命名。所以,

import collection.JavaConversions._ 

是一個偉大的想法,而

import collection.JavaConversions.{asJavaConcurrentMap,enumerationAsScalaIterator,...} 

是令人難以置信的尷尬。更重要的是,在Scala中,你可以把你的進口在任何範圍內:

package mypackage { 
    class MyClass { 
    def myGraphicalWidgetHandler { 
     import java.awt._ 
     ... 
    } 
    ... 
    } 
    ... 
} 

這確實有助於保持命名空間的雜亂感貫穿整個文件。你也可以選擇重命名,你知道會發生衝突進口的部分:

import java.awt.{List => AwtList, _} 

相反,在Java中,你只限於進口全球範圍內,你不能將其重命名;你也沒有隱式轉換,所以只需要引入那些你正在尋找的東西就沒關係。另一方面,您擁有強大的IDE支持,可以幫助您找到您正在查找的類併爲您導入。所以對於Java來說,有一個合理的理由可以讓你的IDE能夠根據你的需要而不是你決定抓住所有東西。就個人而言,我仍然發現這太尷尬,大部分時間只使用通配符導入。

+1

我很想Java的這些功能(範圍+重命名)...... – Stefan 2013-03-23 16:26:01

2

對於Java方面:使用通配符導入絕對沒有錯!在運行時沒有性能缺陷,因爲只加載實際使用的類。

java的導入機制發生在編譯時。它唯一用於的是,如果在代碼中使用類Date,則在同一個包中沒有類Date,導入機制將用於在其中一個導入語句中查找類Data。

所以它只是「找出你正在參考什麼類」。沒有什麼可以改變你的運行時性能。

+0

由於Andiaz說如果在兩個不同的導入包中存在兩個相同簡單名稱的類,則只會有問題。 – Chris 2011-03-15 11:50:54

+1

誠然,性能方面沒有什麼區別,但如果有一天您的構建過程會抱怨未知的Foo類,並且您有通配符導入,那麼祝您好運,以確定它突然從哪個包丟失。去過也做過。 – Imre 2012-10-12 12:41:30

12

那麼,通過指定完整的類名來消除歧義。所以,當你明確指出要導入哪個類時,它更容易理解代碼的意圖。 Java 1.2也浮現在腦海中:

import java.util.*; 
import java.awt.*; 

... 
List blah; 

這在Java 1.1中運行良好。但是,在Java 1.2中,List接口被添加到java.util中,並且過去很好的代碼不再工作。許多開發商哭了。

8

在Java中,使用通配符進行輸入或不輸入主要是代碼可維護性問題和[un-]意願處理導入歧義(當兩個導入的包具有相同名稱的成員時)。另一方面,從意識形態的角度來看,導入整個包(例如,java.sql._)意味着您想要有一致的行爲,並避免從同一包中導入多行內容。

的大部分是真實的斯卡拉,不同之處在於:

  1. 如果要導入同一類的多個成員沒有污染的代碼,並在同一時間,避免可能出現的歧義,斯卡拉提供了一個特殊的語法:import java.io.{File, FileInputStream};
  2. 在Scala中,您可以給導入的成員提供別名,以處理含糊之處:import java.lang.{Double=>JDouble};
  3. 正如你所提到的那樣,使用通配符導入可以將上下文添加到上下文中,這可能會導致另一層含糊不清(所以這是另一個需要考慮的原因);

因此,總而言之,在Scala中IMO,通配符導入語法應該僅用於這種情況,當您使用特定的庫並希望它一致地行事時(在Scalaz的情況下,所有必需的成員,隱式轉換等等)。

+0

我喜歡你的重點導入implicits,特別是在包對象中定義的。 – 2011-03-15 13:09:23