Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / June 2006

Tip: Looking for answers? Try searching our database.

Avoid calling non-final methods in a constructor: Applies to static methods too?

Thread view: 
Oliver Wong - 07 Jun 2006 17:09 GMT
   I'm aware of and follow the dogma that one should not call non-final
methods in a constructor. However, I'm wondering whether this applies to
static methods as well. My understanding of the reasoning behind this rule
is that subclasses may see fields in some unstable state, which tells me
that the rule need not apply to static methods. However, this code analysis
tool is reporting a warning with the following code:

<code>
public class Test {
 public Test() {
   staticMethod();
 }

 public static void staticMethod() {
   //Does nothing.
 }
}
</code>

   Should I be declaring the staticMethod as being final? Will that even
have any effect on the semantics of the code? Or should I rather submit this
as a potential bug fix to the tools author?

   - Oliver
Chris Uppal - 07 Jun 2006 17:20 GMT
> <code>
> public class Test {
[quoted text clipped - 11 lines]
> have any effect on the semantics of the code? Or should I rather submit
> this as a potential bug fix to the tools author?

Final doesn't apply to static methods 'cos they don't override anyway (I don't
suppose Java will even let you combine the two, though I haven't tested it).
Unless the linting tool is just warning you about calling static methods /at
all/ (which seems a touch too sweeping even for my taste ;-) or -- more
likely -- warning you about calling a static method via an instance referrence
(in this case the implicit "this."), then I think it must be a bug.

   -- chris
Mike Schilling - 07 Jun 2006 18:16 GMT
> Final doesn't apply to static methods 'cos they don't override anyway (I
> don't
[quoted text clipped - 6 lines]
> referrence
> (in this case the implicit "this."),

Are you saying that in

   void meth()
   {
       staticMethod();
   }

   static void meth2()
   {
       staticMethod();
   }

   static void staticMethod()
   {
   }

the first call to staticMethod() is done implicitly via "this" and while the
second call simply finds that staticMethod() is in scope?  I am dubious :-)

> then I think it must be a bug.
Chris Uppal - 07 Jun 2006 19:09 GMT
> Are you saying that in
>
[quoted text clipped - 15 lines]
> the second call simply finds that staticMethod() is in scope?  I am
> dubious :-)

I'm by no means certain which of the two candidate "explanations" apply from
the JLS. I suspect that both apply.  But it doesn't really matter -- the
question is whether Oliver's linting tool interpreted it like that.

BTW, I did try putting
   static final void aMethod() {}
into a class and javac accepted it quite happily -- which strikes me as stupid.
So then I tried Piotr's suggestion -- that it prevents you from creating
another static method with the same name/signature in a subclass -- and he's
right.  I think that's /really/ stupid...

   -- chris
Piotr Kobzda - 07 Jun 2006 22:19 GMT
> So then I tried Piotr's suggestion -- that it prevents you from creating
> another static method with the same name/signature in a subclass -- and he's
> right.  I think that's /really/ stupid...

Not as stupid as it looks like, IMHO. ;)

Formally there are adequate paragraphs in JSL which explains why this
construct is allowed, in particular see 8.4.3.2, 8.4.3.3 and 8.4.8.2 (JLS3).

I've not based any solution on final static methods yet, but I can
imagine some potential usages of such kind of methods.

Having for example:

  class A {
    static final void m1() {}
  }
  class B extends A {
  }

we can call A's class m1 method with:

  A.m1();

or (what is a key here) with:

  B.m1();

This is of course not any special property of final static methods
(non-final static methods can be invoked the same way). But thanks to a
final there is no possibility to hide our A's m1 method from any class
subclassing A (e.g. from B).

So using final static methods we can create a special methods (e.g.
factory, registration, authentication etc.). And we know that nowhere in
our class hierarchy is a method accidentally (or not) "replacing" our
method's functionality.

Of course, as I said before, all static methods calls are preformed in a
static way (that means methods lookup is performed in compile time
only). So even when we'll make A's m1 method non-final, and than add
method hiding it to class B, our both above example calls will still
call A's m1 until we do not recompile them again.

Regards,
piotr
Chris Smith - 07 Jun 2006 23:39 GMT
> > So then I tried Piotr's suggestion -- that it prevents you from creating
> > another static method with the same name/signature in a subclass -- and he's
> > right.  I think that's /really/ stupid...
>
> Not as stupid as it looks like, IMHO. ;)

Nah, it's definitely stupid.  It assigns yet another completely new
meaning to final, which is only superficially similar to the existing
meaning for instance methods.

Signature

Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation

Piotr Kobzda - 08 Jun 2006 08:25 GMT
>>> So then I tried Piotr's suggestion -- that it prevents you from creating
>>> another static method with the same name/signature in a subclass -- and he's
[quoted text clipped - 4 lines]
> meaning to final, which is only superficially similar to the existing
> meaning for instance methods.

Completely new meaning? That meaning is given to final at the beginning
of Java (check JLS first! ed.). Using final methods (8.4.3.3) prevents
us from _overriding_ (8.4.8.1) of instance methods or _hiding_ (8.4.8.2)
of static methods. Which in fact gives *very similar* meaning to final
in both cases, it simply prevents from providing a "new version" of
method in subclasses.
What's stupid in that?

Regards,
piotr
Chris Uppal - 08 Jun 2006 15:53 GMT
> Completely new meaning? That meaning is given to final at the beginning
> of Java (check JLS first! ed.). Using final methods (8.4.3.3) prevents
[quoted text clipped - 3 lines]
> method in subclasses.
> What's stupid in that?

Well, I'm still sticking by the word "stupid".  In this particular case it's
conflating two notions which are a lot less closely related than they might
look to a beginner.  That's confusing for beginners, and irritating for purists
(and are there any other categories of programmer I care about ? Hmm.... ;-)

More generally, it's part-and-parcel with the mess surrounding static method in
Java.  It's not the static methods themselves that I object to (though I don't
think they are done right), but all sorts of silly little details in the spec,
and so on, give the (IMO very strong) impression that the Java designers simply
didn't understand the difference between static methods (more properly called
functions), and real (OO) methods.  My three favourite examples.

1 (the famous one) You can invoke a static method "via" a reference to an
instance.

2 The recommended order of keywords gives access control primacy over the
static/non-static distinction, when it is /much/ less important.

3) The method resolution rules in the JVM /require/ that the JVM first finds
the method with the given name/signature, and only /after/ it has done that is
it allowed to check whether the discovered method is static or not (and to
throw an error if its of the wrong kind) -- even though invokestatic and
invokevirtual (and variants) are not interchangeable instructions.

I get the impression that the designers had some sort of fuzzy idea of "static"
members being somehow shared between all the instances.  And that -- above
all -- strikes me as stupid.

   -- chris
Chris Smith - 08 Jun 2006 16:02 GMT
> > Nah, it's definitely stupid.  It assigns yet another completely new
> > meaning to final, which is only superficially similar to the existing
[quoted text clipped - 4 lines]
> us from _overriding_ (8.4.8.1) of instance methods or _hiding_ (8.4.8.2)
> of static methods.

Indeed, and the part about "hiding" of static methods is new versus a
hypothetical language where it is illegal to use the final modifier on a
static method.  That hypothetical language is more consistent and
predictable than Java, hence the adjective "stupid" attached to the
choice to allow final on static methods.

> Which in fact gives *very similar* meaning to final
> in both cases,

I don't think it's very similar at all.  In one case, you are prevented
from redefining the behavior of existing code by changing the behavior
for an existing method when executed in the context of a subclass.  In
the other place, you are prevented from using a certain identifier to
define a completely new and unrelated static method in a subclass.  The
fact that these two entirely different things look similar is confusing
and counts as a fault in the language.  Why would anyone want to define
a language feature as if to pretend that they really are similar, and
thus further the confusion?

Signature

Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation

Chris Smith - 08 Jun 2006 16:06 GMT
> I don't think it's very similar at all.  In one case, you are prevented
> from redefining the behavior of existing code by changing the behavior
> for an existing method when executed in the context of a subclass.

Okay, so that was a little awkward.  It can be cleaned up a little by
using more theoretical OO technology.

In one case, you are prevented from redefining the behavior of existing
code by changing the method by which an object of the subclass responds
to the same message.  In the other place, you are prevented from
defining essentially a new message with the same name as the existing
message.

Signature

Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation

Mike Schilling - 08 Jun 2006 17:52 GMT
>> I don't think it's very similar at all.  In one case, you are prevented
>> from redefining the behavior of existing code by changing the behavior
[quoted text clipped - 8 lines]
> defining essentially a new message with the same name as the existing
> message.

That's the point, I think.  There is no relationship between the two methods
defined in

   class Super{ public static void a() {}}
   class Sub extends Super {public static void a() {} }

except that they have the same name.  One hides the other, but that's quite
different from overriding it.
Piotr Kobzda - 12 Jun 2006 15:32 GMT
> Having for example:
>
[quoted text clipped - 11 lines]
>
>   B.m1();

Heaving the above example the following description is not quite true...

> Of course, as I said before, all static methods calls are preformed in a
> static way (that means methods lookup is performed in compile time
> only). So even when we'll make A's m1 method non-final, and than add
> method hiding it to class B, our both above example calls will still
> call A's m1 until we do not recompile them again.

We don't have to recompile it again to see a different results -- that's
my earlier intuitive feeling on how static final methods are treated by
the compiler.
I've checked resulting bytecode, and invokestatic B.m1() still exists
for the above last usage example.
Nevertheless B.m1() results in A.m1() invocation at runtime. That is
because of Java method resolution mechanism, which is common for both
static and instance methods (see JVMS 2nd ed. - 5.4.3.3 Method Resolution).

Thus we have a kind of dynamic lookup of static methods within class
hierarchy (starting class B in my example) -- similar to the lookup
performed during invokespecial instruction calls.

Backing to the discussion on meaning of final for static methods, I'm
still the one -- having respect to all opinions given here -- for whom
using it makes some sense, final simply gives us an ability to tell the
others: "don't care about hidings of this method" and that's all for me.

Regards,
piotr
Chris Uppal - 13 Jun 2006 10:18 GMT
> Thus we have a kind of dynamic lookup of static methods within class
> hierarchy (starting class B in my example) -- similar to the lookup
> performed during invokespecial instruction calls.

Yes.  The JVM-level static method lookup is distinctly strange, and it has
definite resemblances to virtual method lookup.  I have always considered this
to be a mix of (a) a sensible strategy to ensure binary compatibility as static
members are migrated around the class hierarchy, and -- less importantly -- (b)
another example of the arbitrary weirdness surrounding static members in Java.

> Backing to the discussion on meaning of final for static methods, I'm
> still the one -- having respect to all opinions given here -- for whom
> using it makes some sense, final simply gives us an ability to tell the
> others: "don't care about hidings of this method" and that's all for me.

Fair enough.  I wasn't disputing your facts (indeed, I learned from you here);
and what's left is a value judgement and/or a question of interpretation.  If,
as it seems to you, this feature is reasonably consistent or otherwise a good
design choice, then who can say you are wrong ?  I, personally, disagree (and
it seems that Chris Smith does too -- we Chrises stick together), but
presumably a certain J Gosling would agree with your interpretation ;-)

   -- chris
Piotr Kobzda - 07 Jun 2006 17:45 GMT
>    Should I be declaring the staticMethod as being final? Will that even
> have any effect on the semantics of the code?

The only benefit of using final static method is to prevent against
declaration of another static method with the same signature in a
subclasses, no other semantical consequences holds. In other words
static methods are always called in static way, that is using
invokestatic bytecode instruction (invokevirtual or invokespecial are
never used for static methods).

> Or should I rather submit
> this as a potential bug fix to the tools author?

I think you should.

Regards,
piotr
Dale King - 11 Jun 2006 02:08 GMT
>    I'm aware of and follow the dogma that one should not call non-final
> methods in a constructor. However, I'm wondering whether this applies to
> static methods as well. My understanding of the reasoning behind this
> rule is that subclasses may see fields in some unstable state, which
> tells me that the rule need not apply to static methods. However, this
> code analysis tool is reporting a warning with the following code:

That dogma is a little overstated. You do need to be careful when
calling non-final instance methods, but saying that you should never
call non-final methods goes a bit too far. The more precise rule is that
you should not call non-final methods whose implementations depend on
the instance state.

For example, I have no problem with code that calls methods that depend
only on constants. But the problem is there is no way to force that from
the superclass. It would be nice if there were an annotation to force
subclasses to not use instance state in a method.

Signature

 Dale King



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.