3

In Java, static methods and variables can be accessed through object reference, like in the program below, which is working absolutely fine:

//StaticDemo.java
class StaticVerifier{
    private int a,b;
    public StaticVerifier(int a,int b){
        this.a = a;
        this.b = b; 
        System.out.println("Values are "+this.a+" "+this.b);
    }   
    public static void takeAway(){
        System.out.println("This is a static method...");
    }
}
public class StaticDemo{
    public static void main(String[] args){
        StaticVerifier sv = new StaticVerifier(3,4);
        sv.takeAway();
    }
}

But when I tried the same code converted in C# its not allowing the object to access the static method and giving compile time error. See the code and associated error below:

//StaticDemo.cs
using System;
public class StaticVerifier{
    private int a,b;
    public StaticVerifier(int a,int b){
        this.a = a;
        this.b = b; 
        Console.WriteLine("Values are "+this.a+" "+this.b);
    }   
    public static void takeAway(){
        Console.WriteLine("This is a static method...");
    }
}
public class StaticDemo{
    public static void Main(string[] args){
        StaticVerifier sv = new StaticVerifier(3,4);
        sv.takeAway();                  // here, unable to access static methods, but can use classname rather than objectname !
    }
}

Errors:
 StaticDemo.cs(17,3): error CS0176: Member 'StaticVerifier.takeAway()' cannot be
        accessed with an instance reference; qualify it with a type name instead
StaticDemo.cs(10,21): (Location of symbol related to previous error)

Can anybody tell me why C# don't have this accessibility and Java has, though both are based on object oriented paradigm?(I mostly mean "why the vendors had made it so?")

Ankur Shah
  • 801
  • 1
  • 12
  • 26
  • 1
    If java makes a mistake, doesn't mean c# have to. It makes no sense to access static member via instance. If anything it will confuse the future readers. static members belongs to class rather than instance. May be that's the reason c# language designers prevent it. Yet another reason why c# is better than java!. – Sriram Sakthivel Aug 27 '14 at 06:39
  • Java and C# may share similar syntax, but they are two completely different languages with different people deciding on what goes into them. I don't know much about Java but in C# static methods do not rely on an instance of an object, they are called without one. If you are looking for the equivalent it would be `StaticVerifier.takeAway()` – Sayse Aug 27 '14 at 06:39
  • 1
    In a similar question [here](http://stackoverflow.com/questions/610458/why-isnt-calling-a-static-method-by-way-of-an-instance-an-error-for-the-java-co) [Jon Skeet](http://stackoverflow.com/users/22656/jon-skeet) mentions the problem that Java language designers have made. – tafa Aug 27 '14 at 06:42
  • 1
    @Sriram Sakthivel I don't think personal opinion like this "Yet another reason why c# is better than java!" add to the conversation. – Eypros Aug 27 '14 at 06:44
  • 2
    @Eypros I don't see anything wrong in that. To be honest I like to work in java, that doesn't makes my statement is false. If you disagree, you can ignore or better express your disagreement with a reason. – Sriram Sakthivel Aug 27 '14 at 06:49
  • I think something is [here](http://www.davesquared.net/2008/07/why-cant-i-access-static-members-from.html) and [here](http://www.25hoursaday.com/CsharpVsJava.html) – Ankur Shah Aug 27 '14 at 07:10
  • 1
    I think you miss the point. There is not any matter which language is better (it's subjective after all to a large degree). This comment adds nothing to the fact that C# made a clearer choice in this specific issue and java did not (or could not). – Eypros Aug 27 '14 at 07:11

3 Answers3

8

Accessing static members through an instance reference is a quirk of Java's, nothing related to object orientation.

The correct way (both in C# and Java) is to access takeAway via the class reference, StaticVerifier.takeAway(). Java allows you to use an instance reference, but again, that's a quirk, and I believe it's just about only Java that has that quirk.

This quirk of Java's can be very confusing. For instance:

public class Example {

    public static final void main(String[] args) {
        Example e = null;
        e.staticMethod();
    }

    static void staticMethod() {
        System.out.println("staticMethod");
    }
}

One might expect that to fail with a NullPointerException. But it doesn't, because staticMethod is static, so you don't need an instance to call it, so the fact that e is null is irrelevant.

Accessing the static through an instance reference also results in unnecessary bytecode being generated. e.staticMethod(); results in:

2: aload_1       
3: pop           
4: invokestatic  #2                  // Method staticMethod:()V

e.g., the contents of e are loaded and then popped. But Example.staticMethod(); just generates

2: invokestatic  #2                  // Method staticMethod:()V

Not that it really matters, the optimizer in the JVM will probably fix it, but...

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Thank u vry much! and +1 for this in depth explaination... :) – Ankur Shah Aug 27 '14 at 07:00
  • One more thing! Can you plz tell me the **software** to check/see the **bytecode**? – Ankur Shah Aug 27 '14 at 10:15
  • 1
    @AnkurShah: If you have a compiled class in your class path, you can get the disassembled bytecode for it using the [`javap` tool](http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javap.html): `javap -c ClassName`. – T.J. Crowder Aug 27 '14 at 10:18
4

In Java the call

sv.takeAway();

is actually compiled to

StaticVerifier.takeAway()

You can check it by calling javap -c StaticVerifier.class.

A good IDE will warn you if you call a static method on instance. So C# is just more strict in this.

ponomandr
  • 1,523
  • 13
  • 21
  • I wouldn't call the C# "more strict" - I'd call it "coherent", and Java's approach "incoherent". – Dave Doknjas Aug 27 '14 at 14:38
  • Yes, it's considered to be a language design mistake. C# simply avoided it – ponomandr Aug 27 '14 at 15:16
  • Maybe Java's language designers got this (accessing static members via an instance) from VB - the VB language designers used no discretion at all when deciding which features to add. – Dave Doknjas Aug 27 '14 at 15:48
2

Because in Java sv.takeAway() actually mean StaticVerifier.takeAway() an this little confusing when you access static method via object reference (it is fun that sv can be null and all will work just fine).

In C# they decide to not include such confusion in language and have only one way to access statics e.g. StaticVerifier.takeAway()

talex
  • 17,973
  • 3
  • 29
  • 66