Win a copy of Terraform in Action this week in the Cloud forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Rob Spoor
  • Bear Bibeault
Saloon Keepers:
  • Jesse Silverman
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
Bartenders:
  • Piet Souris
  • Al Hobbs
  • salvin francis

Overriding Static Method Question

 
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
First off, I do know that you cannot override final or static methods, . However, what I'm not clear about is why the compiler should complain about this:



The compiler error is:



Hmm. Funny message. The compiler is contradicting the rules of the Java specification which make it quite clear that I cannot override static methods. And yet here it is complaining about access modifiers. But the only way I can break access modifiers is if I'm overriding. Why is this error message even there?

Comments?
 
Ranch Hand
Posts: 210
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The compiler is behaving just the way it should. Although, static methods cannot be overridden, you can hide them which would have been the case if you had not assigned weaker access privileges. The compiler is not required to enforce this.

More details here:
OverridingVsHiding
 
Ranch Hand
Posts: 140
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That static methods are inherited from super class. And you are trying to restrict the visibility of the method(f()) here by making it private. Thats why this error message.
 
Arron Ferguson
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Rajshekhar:

Incorrect. Static methods are not inherited. The SCJP authors makes this clear, the Java specification makes this clear.

Prateek:

The compiler is most definitely not behaving as it should. It's implying that I've overridden the method but you cannot override static (class methods). This is contradiction from the Java compiler and a bug. I can't believe this is in there, seriously.
 
Rajshekhar Paul
Ranch Hand
Posts: 140
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Arron, I am sorry for the misleading information.
But when I try to compile this code


I get compile time error.
"Cannot reduce the visibility of the inherited method from Aaa".

I had checked with your code also. And I got the same message as above.
It seems that correct terminalogy is not used the error messages in JVM.

And if you read the Overriding Vs Hiding explanation in the FAQ section in JavaRanch, you will get an idea of it. There it is mentioned "Sometimes you will see error messages from the compiler that talk about overriding static methods. Apparently, whoever writes these particular messages has not read the Java Language Specification and does not know the difference between overriding and hiding. So they use incorrect and misleading terminology. Just ignore it. The Java Language Specification is very clear about the difference between overriding and hiding, even if the compiler messages are not. Just pretend that the compiler said "hide" rather than "override".."
 
Arron Ferguson
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Rajshekhar:

I guess my point is that the compiler shouldn't be giving misleading information like this. It's not something that I would think 10+ year old technology would so blatantly be doing.

Anyways, thanks for your answer. I guess the idea is to ignore the message.
 
Rajshekhar Paul
Ranch Hand
Posts: 140
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yeap, we should ignore such messages because at such points we can't trust them.
 
Ranch Hand
Posts: 1032
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have read this post several times, and I find it very interesting. Here are some of my thoughts:

1. It's true that the compiler message explained in the first post is incorrect, but that is not the only thing that is incorrect (see 3.)

2. I think that non-private static methods are inherited (the same as static variables.) You could argue that static methods are inherited by the class, and not by the objects of the class, but the fact remains that any object of any given class has access to the static methods of that class as well, and inheritance must be understood as visibility of entities from code that does not need to use the dot operator(.) on a class name other than its own, or on a reference to an instance of a class other than its own. Notice that inheritance is not the same as polymorphism (which is at the core of the overriding mechanism.) Inheritance is a question of visibility at compile time based on the type of a reference, whereas polymorphism involves determining the version of an overridden method to invoke based on the actual type of the object the reference points to, and it happens at runtime (not at compile time.)

For example:

The above outputs:

Static value in A = 1
Static method defined in A returns: In A.f()

If you uncomment line 1, the output will be:
Static value in A = 2
Static method defined in A returns: In A.f()

This illustrates the point that when you declare a static reference in the subclass with the same identifier as a static reference declared in the superclass, the subclass reference simply hides the superclass one.

However, the same unqualified statement is not true for methods, as the code in the first post suggests. This brings us to the next point.

3. I think that not only the compiler is outputting the wrong message, but that it is not allowing behavior that should be allowed. At least, the behavior is not consistent between instance references and instance methods.
If you can define a static reference in a subclass with the same name as a static reference in the superclass, why can't you do the same with static methods? Note that you can do that with static methods, but that is only the case as long as the overriding rules are obeyed (I verified that changing the return type to a not-covariant return type in the subclass method's signature also upsets the compiler,) and that is incorrect behavior in my opinion.There should be no ambiguity, since overriding doesn't come into effect for static methods, so the actual method being invoked could be determined solely based on the type of the reference the method is being invoked on, without regards for the actual object type.

This leads me to the conclusion that that faulty message output by the compiler is a sign of the real problem: The compiler actually thinks f() in the subclass is overriding f() in the superclass!

Any thoughts?
[ December 19, 2008: Message edited by: Ruben Soto ]
 
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think as long as the compiler is concerned , it checks for the overriding rules at first (neither cares its defined as static or non static ) , which causes the exception as faced -lesser accesser specifier for the overriden method in subclass.

Actually when it matters was, when the method was actually called.Where it uses shadowing (hiding) to call the method as explained in another thread.

https://coderanch.com/t/410462/java/java/Static-Methods-Interface
[ December 20, 2008: Message edited by: Juva Yuva ]
 
Master Rancher
Posts: 4062
56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[Prateek]: Although, static methods cannot be overridden, you can hide them which would have been the case if you had not assigned weaker access privileges. The compiler is not required to enforce this.

Not required to enforce what? The compiler is required to prevent programmers from hiding a static method with another static method with weaker access. From JLS 8.4.8.3: "The access modifier (�6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, or a compile-time error occurs." The compiler is behaving correctly according to the specification - except for the incorrect terminology.

[Aaron]: Static methods are not inherited. The SCJP authors makes this clear, the Java specification makes this clear.

No, the Java specification does not agree with this statement. The term inherited is defined in JLS : "The members of a class type (�8.2) are classes (�8.5, �9.5), interfaces (�8.5, �9.5), fields (�8.3, �9.3, �10.7), and methods (�8.4, �9.4). Members are either declared in the type, or inherited because they are accessible members of a superclass or superinterface which are neither private nor hidden nor overridden (�8.4.8)." The fact that they use italics for inherited tells us this is the official definition according to the JLS - this is also the passage you find if you look up "inheritance - term definition" in the index. To be inherited, a member has to be accessible, and not overridden or hidden. There's no requirement that it be non-static. Further, the fact that they said "nor hidden" confirms that static members are being considered here, because the term hidden would only apply to static members.

Various other books may use the term "inherited" differently; that's their prerogative. But that doesn't change the JLS definition.

[Ruben]: 3. I think that not only the compiler is outputting the wrong message, but that it is not allowing behavior that should be allowed.

Obviously I agree with the first point. As for the second, the compiler is doing exactly what the JLS requires here, aside from its misleading language. However I would agree that the JLS could have, and perhaps should have, given a different rule for this. It would not necessarily create any problems to allow programmers to hide a static methods with a static method with weaker access. Or with a completely different return type, or a different throws clause. The two static methods are really unrelated, except for the rules given by the JLS, and the fact that they share the same name.

However, I think the main reason that the JLS regulates hiding they way they do is that doing so makes it easier for programmers to refactor by making a static method into an instance method (or vice versa). This is not an unusual thing to do, in my experience, and it would be harder if your static methods could have incompatible access, return types, and throws clauses. So I think it's not necessarily a bad thing that Java's designers chose these rules.

[Juva]: I think as long as the compiler is concerned , it checks for the overriding rules at first (neither cares its defined as static or non static )

Well, you seem to be ignoring the terminology used in the JLS here, the same way that the author of the compiler error message did. I think that will just create further confusion at this point. When you say "overriding", I can't really tell what you mean, because as I understand the term, it only applies to non-static methods.
 
Ruben Soto
Ranch Hand
Posts: 1032
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
(In reply to Juva)
I understand what the compiler is doing. I just don't think it should be doing it. Why should redefined static methods in a subclass abide by overriding rules? The overriding mechanism is irrelevant for static methods, so why is the compiler enforcing rules that it shouldn't? I'm not claiming the compiler is necessarily wrong. All that I am saying is that it either is wrong, or the reason for which it is right escapes me at the moment.
[ December 20, 2008: Message edited by: Ruben Soto ]
 
Ruben Soto
Ranch Hand
Posts: 1032
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
(In reply to Mike)
Thanks for your answer on this, what you said actually makes perfect sense. I am used to Java's consistency, and while this behavior might seem inconsistent, the reason you give for it is quite plausible. I derive from your post regarding the JLS rules for this case (of which I must confess utter ignorance) that static methods are subject to a set of rules that are identical to the overriding rules, but since overriding isn't a mechanism that comes into play for static methods, they shouldn't be called overriding rules, but rather something else (rules for redefined static methods.)
[ December 20, 2008: Message edited by: Ruben Soto ]
 
Mike Simmons
Master Rancher
Posts: 4062
56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yup. Obviously there are other rules about overriding and hiding which are different, and that's why we have different terms. But the rules mentioned here, about not using a more restrictive access modifier, and not having an incompatible return type or incompatible throws clause - those rules are the same.
 
Arron Ferguson
Greenhorn
Posts: 28
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mike Simmons:

I think you're misinterpreting section 6.4.3 of the JLS. Re-quoting:

Members are either declared in the type, or inherited because they are accessible members of a superclass or superinterface which are neither private nor hidden nor overridden.



In order to be inherited, the following must be true:
  • super-class member has no private access modifier
  • super-class member is not hidden (IOW it's not static)
  • super-class member is not overridden


  • So a super class member that is static cannot be inherited.
     
    Ranch Hand
    Posts: 231
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Aaron:
    So a super class member that is static cannot be inherited.

    Instance methods that are inherited can be overridden.
    Static methods that are inherited can be redefined/hidden

     
    Mike Simmons
    Master Rancher
    Posts: 4062
    56
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    [Aaron]: super-class member is not hidden (IOW it's not static)

    Where do you get this interpretation? It seems to me that ""super-class member is not hidden" would also aply if it is static, but there is no method in the subclass with the same signature.

    Alternately, why do you not apply your same logic to the next line of your post, the third bullet point? Why not say "super-class member is not overridden (IOW it's not an instance method)"? The seems no less logical than your previous statement. I mean, I don't agree with either one so far, but I'm trying to understand how you're getting to this conclusion.
     
    reply
      Bookmark Topic Watch Topic
    • New Topic