简体   繁体   中英

Unlike .Net Why the static member can be accessed by the instance in Java

All, Unlike C#, I found the static member can be accessed by the instance in Java. OK, I don't have any points for this. But actually it cause a problem. Let me explain it with a example.

Say we have two classes exist already.

public class A
{
     public void m1()
     {   
         ...
     } 
} 

publc class B
{
     public void m2()
     {
         A a= new A();
         a.m1();
     }
}

There class had been compiled and deployed. and it always works fine. But for some reason. Someone change the Class A like below.

    public class A
    {
         public static void m1()
         {   
             ...
         } 
    }

So he just compiled A and deployed it . Class B doesn't need to be changed. because the code is the same. Then the exception will happened if didn't compiled Class B .

Exception in thread "main" java.lang.IncompatibleClassChangeError: 
Expecting non-static method A.main() at B.main(b.java:34)

Although it doesn't make sense when calling the static member from the instance variable. But Java allow we do that. I just can't understand why Java allow it ? thanks.

You have to distinguish source code and byte code.

In source code, Java unfortunately allows to access static members via an instance reference. So, you can easily write a.m1() , where a is a variable (as in your example). It is, however, very bad style and thus not recommended.

Static bindings are resolved at compile-time. So the compiler writes the access to the static member directly with the reference to the class into the byte code. So, when analyzing the resulting byte code, you will not find instance references anymore (in regards to static members).

And this distinction is the cause of your exception. The byte code for your class B still contains a call to a dynamically linked method, which simply does not exist in the byte code for class A. Consequence: the exception.

The reason you can't in C# is because the language designers deemed it was bad practice and could confuse people.

Take the following Java example:

class A {
    public static void Foo() {
        System.out.println("A::foo");
    }
    public void Bar() {
        System.out.println("A::bar");
    }
}

class B extends A {
    public static void Foo() {
        System.out.println("B::foo");
    }
    public void Bar() {
        System.out.println("B::bar");
    }
}

public static void main(String[] args) {
    A a = new B();
    a.foo();  // A::foo
    a.bar();  // B::bar
    a = null; // Oh-oh
    a.foo();  // A::foo
}

As you see, even when setting a to null you can still use the instance variable to call the static method. For novice programmers and Monday mornings this looks very confusing. From what I've gathered, most Java developers advice against the practice too.

I'm not that familiar with the current state of Java or which direction they are heading. Most likely this is just something that was allowed years ago but hard to take out as it would possibly break a lot of existing applications.

As I understand your question is 'why' is it allowed? Right? Basically for code evolution these kind of changes are ought to be allowed.

Actually, the change that you are doing is termed as binary incompatible change. The Java Language specification clearly lists out such incompatible change that could break the code. Yes, it is a binary incompatible change but the compiler has no way to know if there's any client application that's using it right? So, it would at max, give you a warning and as a java developer you are expected to know such binary incompatible changes and its repercussions. You as the author of your code know that your code might be used by other libraries and that should discourage you from making such incompatible changes to your codebase (or else it would break the client libraries). The Java compiler has no way to know this right? Therefore, java allows you to change the method definition as this is absolutely essential for code evolution and also because the compiler doesn't know how your code is distributed and used. I hope I could explain the rationale behind allowing such incompatible changes to java code. For more information look here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM