通配符导入Java和Scala中的用法

时间:2011-03-15 11:32:46

标签: java scala wildcard import

最近,我经常听到“你永远不应该使用通配符导入”这样的陈述。所以我想向社区询问这个问题。是否真的永远不会在Java生产代码中使用通配符导入,无论如何?这条规则有例外吗?我对您的个人经历和意见感兴趣。您是否在生产代码中使用它们并将其推荐给其他人?你如何使用它们 - 你能推荐最好的方法吗?

从Scala的角度来看它也很有趣。 Scala也是如此吗?或者Scala中的通配符导入应仅用于演示幻灯片和SO答案吗?

例如,如果你看一下scalaz page,他们建议使用通配符导入,如:

import scalaz._
import Scalaz._   

我认为考虑通常使用通配符导入的隐式转换也很重要。

4 个答案:

答案 0 :(得分:14)

在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 :(得分:12)

好吧,通过指定完整的类名,可以消除歧义。因此,当您明确说明要导入哪个类时,更容易理解代码的意图。 Java 1.2也浮现在脑海中:

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

...
List blah;

这在Java 1.1中运行良好。但是,在Java 1.2中,一个List接口被添加到java.util中,以前的代码已经不再适用了。很多开发者都哭了。

答案 2 :(得分:8)

在Java中,使用通配符进行导入或非导入主要是代码可维护性和[不]处理导入歧义的意愿(当两个导入的包具有相同名称的成员时)。另一方面,从意识形态的角度来看,导入整个包(例如,java.sql._)是非常有意义的是你想要有一致的行为,并避免多行导入相同的包裹。

大部分内容都适用于Scala,区别在于:

  1. 如果要从同一个类中导入多个成员而不污染代码,同时避免可能的歧义,Scala会为此提供特殊语法:import java.io.{File, FileInputStream};
  2. 在Scala中,您可以为导入的成员提供别名,以处理含糊不清的问题:import java.lang.{Double=>JDouble};
  3. 正如您所正确提到的,使用通配符导入会向上下文添加含义,这可能会导致另一种含糊不清的情况(这是另一个需要三思而后行的原因);
  4. 所以,总而言之,IMO,Scala中的通配符导入语法只应在这种情况下使用,当您使用特定的库并希望它一致行动时(如果是Scalaz,则全部使用)到位所需的成员,隐式转换等。

答案 3 :(得分:2)

对于Java方面:使用通配符导入绝对没有错!在运行时没有性能缺乏,因为只加载了实际使用的类。

java的导入机制发生在编译时。它唯一用于的是如果你在代码中使用类Date,那么在同一个包中没有类Date,导入机制将用于在一个数据库中查找类数据进口报表。

所以它所做的只是“找出你引用的类”。什么都不会改变你的运行时性能。