Re: getting used to Java - question about "style"
From: Chris Gray (chris.gray_at_kiffer.be)
Date: 07/06/04
- Next message: wayne: "Re: How to load class files in Tomcat4?"
- Previous message: Andrew Thompson: "Re: Available memory and limit on thread creation"
- Maybe in reply to: Roedy Green: "Re: getting used to Java - question about "style""
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Tue, 06 Jul 2004 22:15:13 +0200
glunk wrote:
> I am working on my very first Java project. I have been familiar with OO
> design for a long time. But I have never put the real thing into practice
> (formerly a VB 6 programmer which only buys you encapsulation). My company
> is shifting away from VB / ASP solutions and bringing in Java and JSP. I
> am one of the ground breakers (God help me).
>
> I am reading a book that a collegue gave me called "The Elements of Java
> Style" by Vermeulen, Ambler, Bumgardner, Metz, Misfeldt, Shur and
> Thompsaon. (A lot of authors for a really skinny book.) Anyway, ONE OF THE
> RULES THAT THEY HAVE IS
>
> "Do not call nonfinal methods from within a constructor."
>
> They go on to explain
>
> "Subclasses may override nonfinal methods and Java will dispatch a call to
> such a mrethod according to the actual type of the constructed object -
> before executing the derived class constructors. This means when the
> constructor invokes the derived method, the derived class may be in an
> invalid state. To prevent this, call only final methods from the
> constructor."
>
> I cannot understand what this says or means. I know that a final method is
> one that cannot be overridden. I do not understand what this parapgraph is
> intending to warn me against doing or why. Can someone explain, preferably
> with an example?
I'll try.
Let's suppose you create a class Foo ...
public class Foo {
and that there is some work which you need to do in various constructors,
maybe in some methods too, so you bundle it into a method frob() ...
public Foo() {
frob();
}
public Foo(String s) {
// do somethig with s ...
frob();
}
void frob() {
// set up some stuff somewhere
}
// etc
}
Now suppose someone extends Foo. They add some new fields, which are
initialised in the subclass's constructors, or maybe in an initialiser.
public class Bar extends Foo {
private static next_seq_no;
private int seq_no = ++next_seq_no;
private String name = "Bar" + seq_no;
...
They can also override frob(), because we didn't make it private or final.
Now the fun starts. :)
When a new object of type Bar is created, the first thing that happens
(after allocating memory for the object) is that a constructor of Foo is
called. If the author of Bar didn't specify a constructor at all then one
will be generated automatically by the compiler:
public Bar() {
super();
}
Or the author of Bar could call Foo's constructor explicitly; for example
public Bar(String s) {
super(s);
...
}
In either case, the constructor of Foo will be called before any Bar code is
executed, including the initializers of seq_num and name. During the call
to the Foo constructor seq_num will be zero and name will be null.
Now look at what happens when the Foo constructor calls frob(). Which frob()
gets called? The one declared in Bar of course, because it is being called
on an object of type Bar. Did the programmer of Bar expect her frob() to be
called with seq_num equal to zero and name equal to null? No she didn't,
because she carefully wrote initialisers for both those variables.
This kind of confusion can be avoided by only calling methods from inside a
constructor if they are either private, or final, or static. (So the text
you quote is too restrictive).
HTH
-- Chris Gray chris@kiffer.eunet.be /k/ Embedded Java Solutions
- Next message: wayne: "Re: How to load class files in Tomcat4?"
- Previous message: Andrew Thompson: "Re: Available memory and limit on thread creation"
- Maybe in reply to: Roedy Green: "Re: getting used to Java - question about "style""
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|