M
markspace
Right. But the constructor also gets run before each individual test,
Huh, thanks for pointing that out, I didn't realize that.
Right. But the constructor also gets run before each individual test,
Premature and probably pointless micro-optimization. I'm having
trouble imagining a class where this could make a measurable
difference in execution speed or a meaningful difference in code size.
First make it readable. Then make it right. Then, as an optional
step if that turns out to be necessary, worry about making it fast.
Professionals understand that readability normally trumps minor
efficiency gains. We can debate which style is clearer, but redundant
code shouldn't be a concern.
Lew said:If optimization were the purpose, then your comment would apply.
No one is worrying about making initialization faster here. What
we're saying is that an unnecessary step (i.e., the redundant
initialization) should not happen unless it actually turns out to be
necessary, and that that is never in the case of member variable
initialization to default ("zero-like") values.
Anyone who claims to program in Java that cannot read the default
initialization of member variables needs to work where the primary
skill is to respond to a flashing orange light on the cash register by
asking their customer, "Would you like fries with that?"
markspace's point that you did not answer was that use of default
initialization for member variables is not less readable and that it
obviates the need for explicit "zero-like" initialization - not
because the extra initialization is slower, a point no one made, but
because it is not necessary. It's the "extra" that's bad, not the
speed.
Jim said:Initializing a field to its default value serves as a useful
indication that the correct operation of the class depends on that
field having that value at that point. Relying on the default
initializer, even though it has the same effect a run time, does not
convey the same information to the reader, since the default
initializers are always applied whether they're needed or not. To me,
omitting the initalizer suggests that the field will receive its real
value sometime later, in a constructor or through some form of delayed
evaluation. It's not a question of understanding the language but of
making the programmer's intentions clear, without creating unnecessary
puzzles.
Lew said:That same point was raised upthread.
This is precisely the point that markspace was refuting when you
answered him. Welcome to the conversation.
Lew said:That same point was raised upthread.
This is precisely the point that markspace was refuting when you
answered him. Welcome to the conversation.
He was saying that adding the redundant initializer does not add that
additional information you just cited, because the action of default
initializers in Java is deterministic and introductory knowledge for
Java programmers. Since all Java programmers know about default
member-variable initialization, adding the second, redundant
initialization does not convey additional information. Therefore the
extra step really is extra, buying nothing, and should be avoided.
I was the one who brought up the idea that there is stylistic
information added by the second initialization, but I do agree with
markspace that the value of that documentation is questionable at
best.
John B. Matthews said:As a longtime student of strongly typed languages without default
initialization, I empathize with the desire for clarity that an
explicit initializer offers. But Java is Java, and I hate redundant
cycles more:
$ make run
cat Allocate.java
public class Allocate {
int i;
}
javac Allocate.java
javap -c Allocate
Compiled from "Allocate.java"
public class Allocate extends java.lang.Object{
int i;
public Allocate();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>")V
4: return
}
$ make run
cat Allocate.java
public class Allocate {
int i = 0;
}
javac Allocate.java
javap -c Allocate
Compiled from "Allocate.java"
public class Allocate extends java.lang.Object{
int i;
public Allocate();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>")V
4: aload_0
5: iconst_0
6: putfield #2; //Field i:I
9: return
}
As a longtime student of strongly typed languages without default
initialization, I empathize with the desire for clarity that an
explicit initializer offers. But Java is Java, and I hate redundant
cycles more:
[...]
public class Allocate {
int i;
} [...]
public Allocate();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>")V
4: return
} [...]
public class Allocate {
int i = 0;
} [...]
public Allocate();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>")V
4: aload_0
5: iconst_0
6: putfield #2; //Field i:I
9: return
}
Out of curiousity, what does the hotspot compiler do with code like
this?
Jim said:Except that as a stylistic issue, which is how the question was
framed, his point is not a refutation but merely a technical
irrelevance. Information that is redundant to the compiler may yet be
useful to the reader. Good programming style is about effective
communication, not parading one's mastery of the language.
Deliberately omitting information that is useful to the reader, simply
because one knows the compiler can do without it, is not good
programming style.
This is precisely the point that Lew claimed no one was making. I've
Correctly.
already explained why I disagree: readability normally trumps minor
efficiency gains. There are exceptions, of course, but not many.
Out of curiousity, what does the hotspot compiler do with code like
this?
readability normally trumps minor
efficiency gains.
Lew said:That would be valid if the omitted information were useful to the
reader. In the case of default values for member variables, the
redundant initialization is not useful to the reader. It simply
restates what every Java programmer already knows. Useless.
Therefore, deliberately not adding the extra redundant unnecessary
repetitive zero-net-effect initialization (which is different from
omitting something that should be there) is good programming style.
markspace said:I guess this is where we do disagree: I don't feel that there's any
readability gains. You know the default value of all instance
variables: 0, null, or false as appropriate. The extra initialization
doesn't do anything, and is just kind of a crutch for the programmer.
I don't want to belabor the point, but I do kinda feel that extra
initializations say "student driver" more than they add any
clarity. Just my opinion, and I don't want to present that as the one
true way or anything, but something to be mindful of as one encounters
other programmers in one's professional life.
Jim Janney said:Not all initializations to default values are created equal. In some
cases the default value is exactly what is needed. Rather more often
it's simply an artifact of the language definition, to be overridden
later in a constructor or through some form of delayed evaluation.
What I described in my previous post is explicitly initializing
fields when and only when the value is going to be used, whether or
not that happens to be the default value. This provides the
programmer with a hint as to which case applies.
Agreed.
For some reason, it has become the normal style to do test setup in an
@Before method rather than a constructor or initialisers, so that's
where people reading tests will look for it. It's preferable to put it
where people will look for it.
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.