开发者

Confusion with a class level and instance level

I have the following class:

public class B {

    public void print() {
    }

    public static void main(String[] args) {
        B B = new B();
        B.print();
    }

}

I was w开发者_StackOverflow社区ondering why the compiler didn't give an error saying it's not a static method. How will it distinguish between the class level and instance level when we have the object with the same as the class?


Because you are accessing the method on an instance of the class. Incidentally the name of the instance is the same as the class name, but since you don't have a static method with this name, the compiler assumes the correct - i.e. an instance method.

If you define the method to be static, then it will again assume the only possible thing - calling a static method on the B class, because the instance doesn't have such a method.

And ultimately, you can't have both a static and a non-static method with the same name.


The JLS discusses and defines the precedence of scoping rules for such cases:

6.3.2 Obscured Declarations

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.

There are other border cases, where variable can be shadowed or hidden. Example:

class Test {
        static int x = 1;
        public static void main(String[] args) {
                int x = 0;
                System.out.print("x=" + x);
                System.out.println(", Test.x=" + Test.x);
        }
}

Again, the compiler follows the JLS and resolves the name according to the spec. The compiler is not smart and does not "figure out" anything, it just follows the spec.


Your question is about the print() method? It works because your variable name is "hiding" the type name, so when you do B.print() it looks at the variable B, which is an instance of class B.

You really shouldn't be calling your variable the same name as the class, at least not with the same case. Things would be clearer for you if you renamed the variable, even if just to 'b'. So:

public class B{

  public void print(){

  }

  public static void main(String[] args){

    B b = new B();

    b.print(); // This works
    B.print(); // this fails

  }

}


Because in that example, print() is a instance method. It is being called from an instance of the class B. If your main looked like this:

public static void main(String[] args){
       print():
       }

then print() would have to be a static method.

It also doesn't matter that your instance is named the same as the class. Since print() is an instance method, it will expect it to be called from an object. It just so happens that you have an object named B that is an instance of class B. Thus there is no problem.


I guess class names and instance variables do not share the same namespace; to the compiler, it is clear that B.print() is being called on the instance and not on the class.

No need to say that this is confusing and should be avoided in real code ;)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜