16

I've been puzzled by the concept of how Java and C# handles namespaces.

Firstly, examples of namespace pollution in some programming languages:

  1. using namespace std for C++.

    Everyone in the industry frowns upon it, but beginners are still taught to do that when starting programming. Here's a SO question about the advice for handling global namespaces

  2. import math.* in Python

When taking a Python class I was told that doing that is not recommended as it pollutes the namespace and firstly allows for access to all methods in the math library without Math.functionname but might cause collisions when writing a method with a duplicate name. It also apparently causes more work for the interpreter since it imports all of the functions, even those that aren't used.

  1. open module in Ocaml Doing this on the toplevel or in ML files Might cause conflicts in naming as well. Especially if writing a library.

  2. JavaScript namespace pollution

The Question:

Does "namespace pollution" (i.e importing a ton of methods that will potentially cause conflict when writing methods) exist in C# and Java (they are similar in many ways)? Why not?

And of course the related questions that are too similar to ask another question:

-Is it because perhaps we have to explicitly @Override things or there's some kind of preventive measure?

-Or it exists, but it's not a thing because it doesn't cause as much havoc as 'using namespace std', and that I'm not aware of it being relatively new to software development out of academic classes?

Example

I find myself using a lot of libraries in C# to avoid having to retype the namespaces for a variable, like 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;

will avoid me having to do System.Xml.Linq.XElement every single time I create an XElement. Much like how we always have to do std::cout in C++

or in Java where I commonly see: import java.util.linkedlist, even import java.util.*

Won't these cause namespace pollution if my class is used elsewhere? Or is it because they will only be "polluting" that particular class scope and not in other classes that might import or inherit my class?

I tried searching for an answer but couldn't find one for this, I might be phrasing the search wrongly though.

EDIT 4/20/2015:

As mentioned by @RealSkeptic, it turns out that Java wildcard imports are also discouraged. source

In addition to the accepted answer and answers below, imports in Java and C# are contained within themselves, so even if someone uses a wildcard kind of import that adds unused method names to the namespace, it does not affect the other classes. On a class level, if a collision in names does occur, Java and C# compilers will throw an error citing ambiguous imports and fail to further compile until the issue is resolved (by renaming functions for example).

Community
  • 1
  • 1
matrixanomaly
  • 6,627
  • 2
  • 35
  • 58
  • 2
    "Won't these cause namespace pollution if my class is used elsewhere?" It's not entirely clear what you mean by this, but a using directive in one source file has no effect on what is imported in other source files. – Jon Skeet Apr 17 '15 at 19:31
  • Similar recommendations exist in Java: Avoid using `import something.*` and don't use the default package (i.e. always have a `package` statement in your classes). The reasons are similar. – RealSkeptic Apr 17 '15 at 19:33
  • @JonSkeet Ah, I meant if I wrote a class/library, shared it, and someone else imports it to use, does it cause pollution like in the case of C++ using namespace std. (not sure if I worded it properly, apologies). – matrixanomaly Apr 17 '15 at 19:34
  • 1
    @matrixanomaly: Unfortunately knowing the details of what's going on in C++, it's hard to say - but imports and using directives don't "pollute" anything in C# or Java. – Jon Skeet Apr 17 '15 at 19:35
  • 1
    "Ambiguous references" would be an issue if you're trying to use a class whose name exists in two namespaces you are `using` in the same file (when compiling)... If that's what you mean. http://stackoverflow.com/questions/14141043/resolving-an-ambiguous-reference – bdimag Apr 17 '15 at 19:39
  • @RealSkeptic that's a good point now that I explicitly Google it: http://stackoverflow.com/questions/147454/why-is-using-a-wild-card-with-a-java-import-statement-bad – matrixanomaly Apr 17 '15 at 19:39
  • Are you making up a problem, which does not exist (programming without namespaces worked well 1 or some years ago)? –  Apr 17 '15 at 19:44
  • @DieterLücking As per the question asks, I am unsure if it exists in Java/C#, where I am trying to understand the differences between programming languages and felt this is something I couldn't find and come to my own conclusion to, so I don't think of that as making up a problem. – matrixanomaly Apr 17 '15 at 19:49

4 Answers4

4

I think Java/C# have a different philosopyh than C++. Let me explain.

When you import something in Java you are only importing it in this part of the code. Let's say you have a class A in package packageA. Furthermore, A imports a class B in package packageB and B imports java.util.LinkedList. In C++, A would include a header-file to use B and in this header-file, you would have an #include for some LinkedList. So the LinkedList would be visible in A. In Java, this is not the case: class A must include java.util.LinkedList on its own to be able to use it. That said, you can still get namespace pollution, but they are more local (typically per-file). This is the reason, why you should avoid the asterisk when using import.

I cannot give a qualified answer for C# since I do not use it, but i think that their philosophy is similar.

Turing85
  • 18,217
  • 7
  • 33
  • 58
4

As already pointed out by others, the problem of namespace pollution is not as prominent in Java as it is in C++. The main reason why namespace pollution is a problem in C++ (and thus called "pollution" in the first place) is that it may cause errors in other modules. This is explained in more detail in Why is “using namespace std;” considered bad practice?.

(The concerning thing here is that this may not only refer to compile errors: For compile errors, you are forced to do something and to resolve ambiguities. The really concerning thing is that it may cause the code to still compile properly, but afterwards simply call the wrong functions!)


In Java, each import affects only the file in which it is contained. This means that the above mentioned pollution can still occur locally in one file. (One could say: It's only the problem of the author who actually caused the namespace pollution, which is just fair)

Analogously to the case in the above mentioned link: Imagine you are using two libraries, "foo" and "bar". And out of laziness (or lack of knowledge of best practices), you are using the wildcard imports:

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();
    }
}

Now imagine you upgrade your version of the "bar" library. And the new version contains a class called bar.Example. Then the above code will fail to compile, because the reference to the class Example is ambiguous.

The same problem can, by the way, also appear with static imports. It's a bit more delicate and subtle, and collisions are a bit more likely. That's why they say that you should use static imports very sparingly.


A side note: Of course, these collisions and ambiguities can easily be resolved. You can always use the fully qualified names instead. Most modern Java IDEs offer a functionality to organize/optimize the imports. For example, in Eclipse, you can always press CTRL+Shift+O, which will (depending on the settings in Preferences->Java->Code Style->Organize Imports) replace all wildcard imports with the individual ones.

Community
  • 1
  • 1
Marco13
  • 53,703
  • 9
  • 80
  • 159
  • So, comparing to C++, pollution doesn't occur when the imports are done on a "global" scale (across all instances), like what Prashant pointed out? – matrixanomaly Apr 18 '15 at 16:55
  • That's right. The author of one file can not cause problems for others by polluting the namespace, because he will only affect his "own namespace" (that is, his own file). – Marco13 Apr 18 '15 at 17:44
1

I think in Java and C# the imports are a short-hand, but the compiler recognizes each reference in the class with the fully-qualified name. So you write new LinkedList<>(), but the compiler understands that in this class at this time you mean new java.util.LinkedList.LinkedList<>().

This solves the problem you were mentioning, I believe, since the full name of the class with the package absolutely must be unique.

shieldstroy
  • 1,307
  • 1
  • 10
  • 24
1

Each class loader in your running Java program maintains its own name-space, which is populated by the names of all the classes it has loaded.

A name-space is a set of unique names for loaded classes that is maintained by the Java Virtual Machine. For example, once a Java Virtual Machine has loaded a class named Volcano into a particular name-space, it is impossible to load a different class named Volcano into that same name-space. You can load multiple Volcano classes into a Java Virtual Machine, however, because you can create multiple name-spaces inside a Java application by creating multiple class loaders. If you create three separate name-spaces (one for each of three class loaders) in a running Java application, then, by loading one Volcano class into each name-space, your program could load three different Volcano classes into your application.

If you are using same class-loader for all the classes in your application then all the classes will be loaded in same name space only once. Class Loader will not load all these classes in subsequent access. also classes in one name space can not interact to classes in other name space.

Lena
  • 350
  • 4
  • 13
Prashant
  • 2,556
  • 2
  • 20
  • 26
  • 1
    I'm NOT the downvoter, but some people dislike it when many `technical` terms are randomly `backticked`. Although this does not affect the usefulness of the answer, someone might go so far and see it as a reason to downvote (but this is just a guess...) – Marco13 Apr 20 '15 at 17:36
  • From a purely technical point, maybe the relationship between a classloader, a package and a namespace is not described as clearly as someone would have expected it (but this also is just a guess..) – Marco13 Apr 20 '15 at 17:39