How to fully qualify a class whose package name collides with the name of a local member?

Well, here's a very interesting Java 7 puzzle for JLS experts. The following code snippet will not compile with either javac or Eclipse:

package com.example; public class X { public static X com = new X(); public void x() { System.out.println(com.example.X.com); // cannot find symbol ^^^^^^^ } } 

The com member seems to completely prevent access to com.* from X However, this does not apply. The following actions, for example:

 public void x() { System.out.println(com.example.X.class); } 

My question (s):

  • How is this behavior justified from JLS?
  • How can I get around this problem.

Note that this is simply a simplification for the real problem in the generated code, where the full qualification of com.example.X is required and the com member cannot be renamed.

Update . I think it could be a similar problem like this: Why can't I "static import"? "equals" method in Java?

+4
source share
3 answers

This is called shading (jls-6.4.2).

A simple name can occur in contexts where it can potentially be interpreted as the name of a variable, type, or package. In these situations, the rules of ยง 6.5 indicate that a variable will be selected in the type preference, and that the type will be selected in the package preference. Thus, it is sometimes impossible to refer to a visible type or package declaration through its simple name. We say that such a declaration is hidden.

+6
source

Your com.example.X.com attribute is not static, so it cannot be accessed through your X class in a static way. You can access it only through instance X.

Moreover, every time you initiate X, it will lead to a new X: I can predict a memory explosion here.

Very bad code :)

+1
source

How can I get around this problem?

Using the full class name here can be a problem, because, as a rule, package names and variable names begin with lowercase letters and thus may collide. But you do not need to use the fully qualified class name to get a reference to the static element of the class; you can refer to it as a class name. Because class names must begin with an uppercase character, they should never interfere with a package name or variable. (And you can import an arbitrary class with its full class name without problems, because the import statement will never confuse the variable name for the package name.)

 public void x() { // System.out.println(com.example.X.com); // cannot find symbol ^^^^^^^ System.out.println(X.com); // Works fine } 
+1
source

All Articles