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

ten*_*shi 9 java import scala wildcard

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

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

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

import scalaz._
import Scalaz._   
Run Code Online (Sandbox Code Playgroud)

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

Rex*_*err 15

在Scala中,通配符导入是必须的,因为许多库期望它们的隐式转换在范围内,但它们并不总是方便地命名.所以,

import collection.JavaConversions._
Run Code Online (Sandbox Code Playgroud)

是一个好主意,而

import collection.JavaConversions.{asJavaConcurrentMap,enumerationAsScalaIterator,...}
Run Code Online (Sandbox Code Playgroud)

令人难以置信的尴尬.更好的是,在Scala中,您可以将导入放在任何范围内:

package mypackage {
  class MyClass {
    def myGraphicalWidgetHandler {
      import java.awt._
      ...
    }
    ...
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

这确实有助于在整个文件中保持命名空间的混乱.您可以有选择地重命名您知道会冲突的部分导入:

import java.awt.{List => AwtList, _}
Run Code Online (Sandbox Code Playgroud)

相比之下,在Java中,您仅限于导入的全局范围,并且您无法重命名它们; 你也没有隐式转换,所以只需要提取你正在寻找的东西.另一方面,您有强大的IDE支持,可以帮助您找到您正在寻找的类,并为您导入它.所以对于Java来说,有一个合理的论据是你应该让你的IDE接受你需要的东西,而不是你决定抓住所有东西.就个人而言,我仍然觉得这太尴尬了,大部分时间都只使用通配符导入.


And*_*son 12

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

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

...
List blah;
Run Code Online (Sandbox Code Playgroud)

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


Vas*_*iuk 8

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

Scala的大部分内容都是如此,区别在于:

  1. 如果你想导入同一类的多个成员没有污染的代码,并在同一时间,避免可能出现的歧义,Scala提供了一个特殊的语法:import java.io.{File, FileInputStream};
  2. 在Scala中,你可以将导入的成员是别名,用于处理歧义:import java.lang.{Double=>JDouble};
  3. 正如您正确提到的那样,使用通配符导入会向上下文添加含义,这可能会导致另一种含糊不清的情况(这是思考的另一个原因);

总而言之,IMO,Scala中的通配符导入语法只应在这种情况下使用,当您使用特定的库并希望它一致行动时(如果是Scalaz,则拥有所有必需的成员,隐式转换等等).