6

What are the rules Java uses to resolve dotted identifiers?

For example:

import Foo.Bar;

class Foo
{
    public static class Bar
    {
    };
};

Now, Foo.Bar can refer to either the imported class Bar or the one defined in the source code. How is this kind of ambiguity resolved?

I have tried this one case so I know what happens in practice, but I'm looking for more than that; I want to know the underlying rules. For example, if Foo.Bar exists in the source file, can I still refer to the imported class Foo.Bar.Baz? What if Foo.Bar is a package and also a class? If the compiler can't find Foo.Bar in the closest Foo, does it just give up, or does it keep looking for other Foos until it either runs out or finds one that matches?

(Incidentally, I have found the relevant bit in the language specification. It doesn't help much...)

David Given
  • 13,277
  • 9
  • 76
  • 123
  • 2
    If all code follows the recommended Java naming conventions, then this never arises: package names are always fully lower-case, and class names always start with an uppercase letter. If your code doesn't follow that convention, well, what you see in the language specification is what you get. – C. K. Young Jun 13 '11 at 14:29
  • True, but not what I was asking... – David Given Jun 13 '11 at 15:03
  • Right, and that's why my comment is a comment, not an answer. ;-) – C. K. Young Jun 13 '11 at 15:16

1 Answers1

4

To resolve a weird clash like this, the java compiler follows the same rules it uses to resolve things like local variable names clashing with instance field names - it uses the "nearest" declaration. In this case, the local class Foo will win over the imported one.

A clash can also happen when two classes of the same name is being imported. The most common example is java.util.Date and java.sql.Date. If you have imported them both into your class, you must refer to them using their fully qualified name.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • -1 for ignoring the question - "I have tried this one case so I know what happens in practice, but I'm looking for more than that; I want to know the underlying rules." – Zach Jun 13 '11 at 14:30
  • I notice that not only does trying to import both `java.util.Date` and `java.sql.Date` fails, but importing `java.util.*` and `java.sql.*` now errors if I refer to an unqualified `Date` --- which is a level of intelligence that frankly I wasn't expecting. What about the case when `Foo` exists locally, hiding the imported `Foo`, but does not provide `Foo.Bar` but the imported one does? Will the local one prevent access to `Foo.Bar` (which would seem sensible)? And is there any way to access the global namespace explicitly, like a leading `::` in C++? – David Given Jun 13 '11 at 16:12