【问题标题】:Wildcard imports usage in Java and ScalaJava 和 Scala 中的通配符导入用法
【发布时间】:2011-07-15 17:29:12
【问题描述】:

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

从 Scala 的角度来看它也很有趣。这同样适用于 Scala 吗?或者 Scala 中的通配符导入应该只在演示幻灯片和 SO 答案中使用?

例如,如果您查看 scalaz page,他们建议使用通配符导入,例如:

import scalaz._
import Scalaz._   

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

【问题讨论】:

  • 你不应该听以“你不应该”开头的建议。
  • @musiKk:我在尝试 :) 但如果你经常听到它,你就会开始怀疑自己......
  • @musiKk,你永远不应该听以“你永远不应该......太频繁”开头的建议;)
  • 您永远不应该关心 Java 导入。除了在极少数情况下防止名称冲突之外,它们没有任何价值。 IDE 应该照顾他们。对于scala,是否缺少这样的IDE支持?

标签: java scala wildcard import


【解决方案1】:

在 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 只提供您需要的东西,而不是您决定获取所有东西。就个人而言,我仍然觉得这太尴尬了,大部分时间只使用通配符导入。

【讨论】:

    【解决方案2】:

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

    import java.util.*;
    import java.awt.*;
    
    ...
    List blah;
    

    这在 Java 1.1 中运行良好。然而,在 Java 1.2 中,一个 List 接口被添加到 java.util 中,并且过去很好的代码不再工作了。很多开发者都哭了。

    【讨论】:

      【解决方案3】:

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

      大部分内容都适用于 Scala,不同之处在于:

      1. 如果您想从同一个类中导入多个成员而不污染代码,同时避免可能的歧义,Scala 为此提供了一种特殊语法:import java.io.{File, FileInputStream};
      2. 在 Scala 中,您可以为导入的成员指定别名,以处理歧义:import java.lang.{Double=>JDouble};
      3. 正如您正确提到的,使用通配符导入会在上下文中添加隐含,这可能会导致另一个级别的歧义(所以这是另一个三思而后行的理由);

      因此,总而言之,Scala 中的 IMO 通配符导入语法应仅在使用特定库并希望其始终如一的情况下使用(在 Scalaz 的情况下,具有所有必需的成员,隐式转换等)。

      【讨论】:

      • 我喜欢你对导入隐式的强调,尤其是在包对象中定义的。
      【解决方案4】:

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

      java 的导入机制发生在编译时。它的唯一用途是,如果您在代码中使用 Date 类,则在同一包中没有 Date 类,导入机制将用于在其中一个导入语句中查找类 Data .

      所以它所做的就是“找出你引用的类”。没有什么可以改变您的运行时性能。

      【讨论】:

      • 正如 Andiaz 所说,只有在两个不同的导入包中存在两个具有相同简单名称的类时才会出现问题。
      • 没错,性能方面没有区别,但如果有一天你的构建过程抱怨未知类 Foo,并且你有通配符导入,那么祝你好运,确定它突然从哪个包中丢失了。去过那里,做到了。
      猜你喜欢
      • 2013-03-16
      • 1970-01-01
      • 2013-06-03
      • 2017-08-05
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-02
      • 1970-01-01
      相关资源
      最近更新 更多