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

旧时模样 提交于 2019-12-07 08:15:30

问题


OK, here's a very curious Java 7 language puzzle for the JLS specialists out there. The following piece of code won't compile, neither with javac nor with 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  ^^^^^^^
    }
}

It appears as though the member com completely prevents access to the com.* packages from within X. This isn't thoroughly applied, however. The following works, for instance:

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

My question(s):

  • How is this behaviour justified from the JLS?
  • How can I work around this issue

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

Update: I think it may actually be a similar problem like this one: Why can't I "static import" an "equals" method in Java?


回答1:


This is called obscuring (jls-6.4.2).

A simple name may occur in contexts where it may potentially be interpreted as the name of a variable, a type, or a package. In these situations, the rules of §6.5 specify that a variable will be chosen in preference to a type, and that a type will be chosen in preference to a package. Thus, it is may sometimes be impossible to refer to a visible type or package declaration via its simple name. We say that such a declaration is obscured.




回答2:


Your attribute com.example.X.com is not static so it can't be accessed via your X class in a static way. You can access it only via an instance of X.

More than that, each time you will instanciate an X, it will lead to a new X : I can predict a memory explosion here.

Very bad code :)




回答3:


How can I work around this issue?

Using a fully qualified class name here can be a problem because, in general, package names and variable names both start with lower case letters and thus can collide. But, you do not need to use a fully qualified class name to gain a reference a class's static member; you can reference it qualified just by the class name. Since class names should start with an upper case character, they should never collide with a package name or variable. (And you can import an arbitrary class with its fully qualified class name without issue, because the import statement will never confuse a variable name for a package name.)

public void x() {
    // System.out.println(com.example.X.com);
    // cannot find symbol     ^^^^^^^

    System.out.println(X.com);  // Works fine
}


来源:https://stackoverflow.com/questions/19406673/how-to-fully-qualify-a-class-whose-package-name-collides-with-a-local-member-nam

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!