java - Java 或 C# 中是否存在命名空间污染(如在 C++ 中)?

标签 java c# c++ namespaces

我一直对 Java 和 C# 如何处理命名空间的概念感到困惑。

首先,一些编程语言中命名空间污染的例子:

  1. 使用命名空间 std 用于 C++。

    行业中的每个人都对此表示不满,但初学者在开始编程时仍会被教导这样做。 Here's a SO question about the advice for handling global namespaces

  2. 在 Python 中导入 math.*

在学习 Python 类(class)时,有人告诉我不建议这样做,因为它会污染命名空间,并且首先允许在没有 Math.functionname 的情况下访问数学库中的所有方法,但可能会导致冲突编写具有重复名称的方法。由于它导入了所有函数,甚至是那些未使用的函数,因此它显然也会给解释器带来更多的工作。

  1. 在 Ocaml 中打开模块 在顶层或 ML 文件中执行此操作 Might cause conflicts在命名方面也是如此。尤其是在编写库时。

  2. JavaScript namespace pollution

问题:

C# 和 Java 中是否存在“命名空间污染”(即在编写方法时导入大量可能导致冲突的方法)(它们在许多方面相似)?为什么不呢?

当然还有相关的问题太相似了,不能再问了:

-是因为也许我们必须明确地@Override 东西还是有某种预防措施?

-或者它存在,但它不是一件事,因为它不会像“使用命名空间标准”那样造成严重破坏,而且我不知道它对于学术类(class)之外的软件开发来说相对较新?

示例

我发现自己在 C# 中使用很多库,以避免必须为变量重新键入 namespace ,例如 XElement

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//the ones above are auto-generated by Visual Studio, too

using System.Xml.Linq;

将避免我每次创建 XElement 时都必须执行 System.Xml.Linq.XElement。就像我们总是必须在 C++ 中做 std::cout

或者在我经常看到的Java中:import java.util.linkedlist,甚至是import java.util.*

如果我的类在其他地方使用,这些会不会造成命名空间污染?还是因为它们只会“污染”特定的类范围,而不是可能导入或继承我的类的其他类?

我尝试搜索答案,但找不到答案,不过我可能用错了搜索措辞。

编辑 2015 年 4 月 20 日:

正如@RealSkeptic 所提到的,Java 通配符导入也是不鼓励的。 source

除了下面接受的答案和答案之外,Java 和 C# 中的导入包含在它们自身中,因此即使有人使用通配符类型的导入将未使用的方法名称添加到命名空间,它也不会影响其他类。在类级别上,如果确实发生名称冲突,Java 和 C# 编译器将抛出一个错误,引用不明确的导入,并且无法进一步编译,直到问题得到解决(例如通过重命名函数)。

最佳答案

正如其他人已经指出的那样,命名空间污染问题在 Java 中并不像在 C++ 中那样突出。命名空间污染在 C++ 中是一个问题(因此首先被称为“污染”)的主要原因是它可能导致其他模块中的错误。这在 Why is “using namespace std;” considered bad practice? 中有更详细的解释。 .

(这里的问题是,这可能不仅仅指编译错误:对于编译错误,你被迫做某事并解决歧义。真正令人担忧的是它可能会导致代码仍然可以正确编译,但之后只是调用了错误的函数!)


在 Java 中,每个 import 只影响包含它的文件。这意味着上面提到的污染仍然可以在一个文件中本地发生。 (可以说:实际上造成命名空间污染的只是作者的问题,这很公平)

类似于上述链接中的情况:假设您正在使用两个库,“foo”和“bar”。出于懒惰(或缺乏最佳实践知识),您正在使用通配符导入:

import foo.*:
import bar.*:

class MyClass {
    void someMethod() {

        // Assume that this class is from the "foo" librariy, and the
        // fully qualified name of this class is "foo.Example"
        Example e = new Example();
    }
}

现在假设您升级了“bar”库的版本。新版本包含一个名为bar.Example 的类。那么上面的代码将无法编译,因为对类 Example 的引用不明确。

顺便说一下,static imports 也会出现同样的问题。 .它更加微妙和微妙,碰撞的可能性更大。这就是为什么他们说您应该非常谨慎地使用静态导入。


附注:当然,这些冲突和歧义很容易解决。您始终可以使用完全限定名称。大多数现代 Java IDE 都提供了组织/优化导入的功能。例如,在 Eclipse 中,您始终可以按 CTRL+Shift+O,这将(取决于 Preferences->Java->代码样式->组织导入)将所有通配符导入替换为单个的。

关于java - Java 或 C# 中是否存在命名空间污染(如在 C++ 中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29707809/

相关文章:

c++ - 简单的 C++ vector 用法

java - LibGDX/LWJGL 启动应用最大化

java - 泛型/参数化类 Java 命名空间

java - Java如何存储字符串以及子字符串在内部如何工作?

c# - 如何处理资源 (.resx) 文件中的字符串文字

c# - 如何在紧凑的框架中生成大图像

c++ - 有没有更优雅的方法来使用带有独立 if() 的 else 语句

java - HTTP 状态 500 - 在第 6 行处理 JSP 页面/login.jsp 时发生异常。(错误消息标题)

c# - 可视化 Web 开发人员(快速): Setting Document Root for Dev Environment

c++ - 为什么 GCC 调用 libc 的 sqrt() 而不使用它的结果?