简体   繁体   English

为什么要定义多个导入?

[英]Why to define multiple imports?

Consider the following import statements: 请考虑以下import语句:

import java.io.*; import java.io. *; // Make sense // 说得通

import javax.servlet.*; import javax.servlet。*;

import javax.servlet.http.*; import javax.servlet.http。*;

Isn't it like that we have included "import javax.servlet. ;" 是不是我们已经包含“import javax.servlet 。;” and therefore it will automatically include the other import statement as well which is "import javax.servlet.http. ; " ? 因此它会自动包含另一个import语句,也就是“import javax.servlet.http . ;”?

Why "import javax.servlet.http.*" is explicitly defined for http ? 为什么为http显式定义了“import javax.servlet.http。*”?

Please clarify and let me know if I'm wrong. 如果我错了,请澄清并告诉我。

No when you import something you import only either a specific class or you import the package and with that all the Classes that belong to that package but not the classes that belong to sub-package of that package. 否,当您导入某些内容时,您只导入一个特定的类,或者导入该包,并导入该属性的所有类,而不是属于该包的子包的类。

Each package contains somewhat related Classes and sub-packages. 每个包都包含一些相关的类和子包。 Classes in sub-package are not necessarily related to classes in parent package. 子包中的类不一定与父包中的类相关。 So it would make no sense to import those as well. 因此,导入这些也没有意义。 This way you avoid needless imports and keep your project clean. 这样您可以避免不必要的导入并保持项目清洁。

Example: 例:
Let's say you are building a View class for your GUI application you may want to separate concerns so you would have JComponents in your View and your Listeners in your Controllers. 假设您正在为GUI应用程序构建一个View类,您可能希望将它们分开,这样您就可以在View中使用JComponents ,在控制器中使用Listeners

So in your View you would import: import javax.swing.*; 因此,在您的视图中,您将导入: import javax.swing.*; this way you would get all the JComponent classes but since you don't need event package in your View it makes sense that import only imports what you actually need. 这样你就可以获得所有的JComponent类,但是因为你不需要在View中使用event包,所以导入只导入你真正需要的东西。 Even tho swing and event package are somewhat related there is no need to import event as well. 即使是swingevent包也有些相关,也没有必要导入事件。

So when you are importing something in Java you are either importing entire package import javax.swing.*; 因此,当您使用Java导入内容时,您要么导入整个包import javax.swing.*; With all the classes that concern the package or you are importing a single class of the package import javax.swing.JButton; 使用与包有关的所有类,或者导入包的一个类import javax.swing.JButton;

You never import package with all of it's sub-packages and their sub-packages etc. As it's highly likely that you do not need all of them. 您永远不会导入包含所有子包及其子包等的包。因为您很可能不需要所有这些包。

Yes, you DO need to do a wildcard import for each package. 是的,您需要为每个包执行通配符导入。

Why? 为什么? As far as the JLS is concerned "com.example" and "com.example.pkg" are unrelated packages. 就JLS而言,“com.example”和“com.example.pkg”是不相关的包。 The notion of a subpackage is mentioned in the JLS, but there is no associated semantic. JLS中提到了子包的概念,但没有相关的语义。 In particular not in the "access" rules. 特别是不在“访问”规则中。 JLS 7.1 says: JLS 7.1说:

"The hierarchical naming structure for packages is intended to be convenient for organizing related packages in a conventional manner, but has no significance in itself other than the prohibition against a package having a subpackage with the same simple name as a top level type (§7.6) declared in that package. “包的分层命名结构旨在方便以传统方式组织相关包,但除了禁止包含具有与顶级类型相同的简单名称的子包之外,它本身没有意义(第7.6节) )在该包中声明。

For example, there is no special access relationship between a package named oliver and another package named oliver.twist , or between packages named evelyn.wood and evelyn.waugh . 例如,有一个名为包之间没有特殊的访问关系oliver和另一包命名oliver.twist ,或命名的包间evelyn.woodevelyn.waugh That is, the code in a package named oliver.twist has no better access to the types declared within package oliver than code in any other package." 也就是说,命名包中的代码oliver.twist必须声明的包中的类型没有更好的访问oliver比任何其他封装代码“。

(And a construct that allows import of a number of unrelated packages has bad consequences ... see below.) (并且允许导入许多不相关的包的结构会产生不良后果......见下文。)

But Why? 但为什么? Because that is the way that the language is designed. 因为这是语言的设计方式。

But WHY? 但为什么? You would need to ask the Java language design team what their thinking was in the early 1990s when the design decisions were being made. 您需要向Java语言设计团队询问他们在20世纪90年代早期做出设计决策时的想法。


But maybe we can see what would happen if there WAS a multi-package wildcard import. 但也许我们可以看到如果有多包通配符导入会发生什么。

Consider this package structure, which is a pretty common pattern: 考虑这个包结构,这是一个非常常见的模式:

  com.example.weazellib - contains the public API classes for the library
  com.example.weazellib.impl - contains implementation classes that 
                               shouldn't be used by external clients

It is a well known fact that programmers are lazy (OK a lot are), so some programmer is likely to write this: 众所周知,程序员很懒(很好),所以一些程序员可能会这样写:

  import com.example.weazellib.**    // hypothetical syntax

He / she will now have both the external API classes and the internal classes in this classes namespace, and it will be easy to accidentally create a dependency on the internals. 他/她现在将拥有此类名称空间中的外部API类和内部类,并且很容易意外地在内部创建依赖项。

(And before you say "make the internal classes package private" ... that doesn't work. There are classes in com.example.weazellib that need to be able use classes in com.example.weazellib.impl . If the latter were package private, then the former would not be able to use them.) (并且在你说“使内部类包私有”之前 ......这不起作用com.example.weazellib中的类需要能够使用com.example.weazellib.impl类。如果后者包私有,然后前者将无法使用它们。)

By contrast, in the world where Java doesn't have wildcards that import package "trees", you can't do that accidentally . 相比之下,在Java没有导入包“树”的通配符的世界中,你不能意外地做到这一点。 You have to deliberately import the impl package. 你必须故意导入impl包。 This is A GOOD THING , and much more important than the "inconvenience" of writing wildcard imports for multiple packages. 这是一件好事 ,比为多个包编写通配符导入的“不方便”要重要得多。


The other problem is that wildcard imports are not good for long term source code stability, and super-wildcards would make it worse. 另一个问题是通配符导入不利于长期源代码稳定性,超级通配符会使情况变得更糟。

Suppose that a programmer decided that importing both com.example.weazellib and com.example.weazellib.impl was the right thing to do in his code ... and uses a super-wildcard to import both. 假设程序员决定在他的代码中导入com.example.weazellibcom.example.weazellib.impl是正确的事情......并使用超级通配符导入两者。 And suppose that he writes his code to use com.example.weazellib.impl.ToesImpl ... as ToesImpl . 并且假设他编写了他的代码以使用com.example.weazellib.impl.ToesImpl ...作为ToesImpl

Now consider what happens if the "weazellib" developer adds a third package com.example.weazellib.impl2 that contains alternative implementation classes ... with the same simple names as the classes in impl ; 现在考虑如果“weazellib”开发人员添加第三个包com.example.weazellib.impl2包含替代实现类的情况会发生什么...与impl的类具有相同的简单名称; eg we now have classes like: 例如我们现在有这样的课程:

com.example.weazellib.impl.ToesImpl
com.example.weazellib.impl2.ToesImpl

What happens? 怎么了? Well now the programmers code has a compilation error in it. 那么现在程序员代码中有一个编译错误。 ToesImpl is ambiguous ... because of the effects of the super-wildcard import pulling in class names from a package that wasn't there before. ToesImpl是不明确的...... 因为超级通配符导入从一个以前没有的包中提取类名的效果

Note that the same problem exists with regular wildcard imports. 请注意,常规通配符导入存在同样的问题。 That's why a lot of people don't use wildcard imports. 这就是很多人不使用通配符导入的原因。 But there is no doubt that super-wildcards would make the problem a lot worse. 但毫无疑问,超级通配符会让问题变得更糟。

It is defined in the spec how import works. 它在规范中定义了导入的工作原理。

See Java Language Spec 请参阅Java语言规范

The reason is javax.servlet and javax.servlet.http are different packages, and import * only brings in the package members. 原因是javax.servlet和javax.servlet.http是不同的包,而import *只引入包成员。

Also, its not a good idea to wild card import as it makes the code less readable. 此外,它不是一个好主意导入外卡,因为它使代码可读性降低。

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

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