简体   繁体   English

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

[英]Wildcard imports usage in Java and Scala

Recently I have heard statements like "you should never use wildcard imports" too often. 最近我经常听到“你永远不应该使用通配符导入”这样的陈述。 So I want to ask community about this. 所以我想向社区询问这个问题。 Should wildcard imports really never ever be used in Java production code, no matter what? 是否真的永远不会在Java生产代码中使用通配符导入,无论如何? Are there exceptions to this rule? 这条规则有例外吗? I interested in your personal experience and opinion. 我对您的个人经历和意见感兴趣。 Do you use them in your production code and would you recommend it to others? 您是否在生产代码中使用它们并将其推荐给其他人? How do you use them - can you recommend the best way to make it. 你如何使用它们 - 你能推荐最好的方法吗?

It also interesting to look at it from Scala perspective. 从Scala的角度来看它也很有趣。 Is the same applies to Scala? Scala也是如此吗? Or wildcard imports in Scala should be only used in presentation slides and SO answers? 或者Scala中的通配符导入应仅用于演示幻灯片和SO答案?

If you will look at scalaz page , for example, they recommend usage of wildcard imports like: 例如,如果您要查看scalaz页面 ,他们建议使用通配符导入,例如:

import scalaz._
import Scalaz._   

I think it also important to consider implicit conversions that are normally imported with wildcards. 我认为考虑通常使用通配符导入的隐式转换也很重要。

In Scala, wildcard imports are a must, since many libraries expect their implicit conversions to be in scope, but they're not always conveniently named. 在Scala中,通配符导入是必须的,因为许多库期望它们的隐式转换在范围内,但它们并不总是方便地命名。 So, 所以,

import collection.JavaConversions._

is a great idea, whereas 是一个好主意,而

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

is incredibly awkward. 令人难以置信的尴尬。 Better yet, in Scala you can put your imports in any scope: 更好的是,在Scala中,您可以将导入放在任何范围内:

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

which really helps keep the namespace clutter down throughout the whole file. 这确实有助于在整个文件中保持命名空间的混乱。 And you can selectively rename parts of the import that you know will conflict: 您可以有选择地重命名您知道会冲突的部分导入:

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

In contrast, in Java, you're restricted to global scope for imports, and you can't rename them; 相比之下,在Java中,您仅限于导入的全局范围,并且您无法重命名它们; you also don't have implicit conversions, so it's okay to only pull in those things that you're looking for. 你也没有隐式转换,所以只需要提取你正在寻找的东西。 On the other hand, you have powerful IDE support that will help find the class that you're looking for and import just it for you. 另一方面,您有强大的IDE支持,可以帮助您找到您正在寻找的类,并为您导入它。 So for Java, there's a reasonable argument to be made that you should let your IDE pull in just what you need rather than you deciding to grab everything. 所以对于Java来说,有一个合理的论据是你应该让你的IDE接受你需要的东西,而不是你决定抓住所有东西。 Personally, I still find this too awkward and just use wildcard imports most of the time. 就个人而言,我仍然觉得这太尴尬了,大部分时间都只使用通配符导入。

Well, by specifiying full classnames you remove ambiguity. 好吧,通过指定完整的类名,可以消除歧义。 So, when you explicitly state which class to import it's a lot easier to understand the intention of the code. 因此,当您明确说明要导入哪个类时,更容易理解代码的意图。 Java 1.2 also comes to mind: Java 1.2也浮现在脑海中:

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

...
List blah;

This worked fine in Java 1.1. 这在Java 1.1中运行良好。 However, in Java 1.2 a List interface was added to java.util, and the code that used to be fine didn't work anymore. 但是,在Java 1.2中,一个List接口被添加到java.util中,以前的代码已经不再适用了。 Lots of developers cried. 很多开发者都哭了。

In Java, using wildcards for import or not is mostly a question of code maintainability and [un-]willingness to deal with import ambiguities (when two imported packages have members with the same names). 在Java中,使用通配符进行导入或非导入主要是代码可维护性和[不]处理导入歧义的意愿(当两个导入的包具有相同名称的成员时)。 On the other hand, from the ideology perspective, it's makes a lot of sense to import the entire pack (say, java.sql._ ) is you want to have a consistent behavior, and avoid multiple lines of imports from the same package. 另一方面,从意识形态的角度来看,导入整个包(例如, java.sql._ )是非常有意义的,你想要具有一致的行为,并避免从同一个包中导入多行。

The most of it is true to Scala, with the difference that: Scala的大部分内容都是如此,区别在于:

  1. If you want to import multiple members from the same class not polluting the code, and, at the same time, avoid possible ambiguities, Scala offers a special syntax for that: import java.io.{File, FileInputStream} ; 如果要从同一个类中导入多个成员而不污染代码,同时避免可能的歧义,Scala为此提供了一种特殊的语法: import java.io.{File, FileInputStream} ;
  2. In Scala you can give aliases to the imported members, for dealing with ambiguities: import java.lang.{Double=>JDouble} ; 在Scala中,您可以为导入的成员提供别名,以处理歧义: import java.lang.{Double=>JDouble} ;
  3. As you correctly mentioned, using a wildcard import you add implicits to the context, which may lead to another level of ambiguities (so that's another reason to think twice); 正如您正确提到的那样,使用通配符导入会向上下文添加含义,这可能会导致另一种含糊不清的情况(这是思考的另一个原因);

So, all in all, IMO, wildcard import syntax in Scala should be used only in the case, when you're working with a specific library and want it to act consistently (in case of Scalaz, to have all the required members, implicit conversion, etc. in place). 总而言之,IMO,Scala中的通配符导入语法只应在这种情况下使用,当您使用特定的库并希望它一致行动时(如果是Scalaz,则拥有所有必需的成员,隐式转换等等)。

For the Java side: There is absolutely nothing wrong with using wildcard imports! 对于Java方面:使用通配符导入绝对没有错! There is no performance lack at runtime because only the Classes which are actually be used are loaded. 在运行时没有性能缺乏,因为只加载了实际使用的类。

The import mechanism of java takes place at compile time. java的导入机制发生在编译时。 The only thing it is used for is if you use the Class Date for example in your code ant there is no class Date in the same package the import mechanism will be used to find the class Data in one of the import statements. 它唯一用于的是如果你在代码中使用类Date作为例子,在同一个包中没有类Date ,导入机制将用于在其中一个import语句中查找类Data。

So all it does is "finding out what class you are referencing to". 所以它所做的只是“找出你所引用的类”。 Nothing what could change your runtime performance. 什么都不会改变你的运行时性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM