Win a copy of Design for the Mind this week in the Design forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

where to declare those %&?!�$ variables

 
Pauline McNamara
Sheriff
Posts: 4012
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm passing on a good question I got along the way nitpicking. Hope y'all feel free to chime in.

Here it is (altered ever so slightly)...

...a question about private static final variables. You wanted me to move those method variables to class level. However, the style guide is all about declaring variables right before you use them...


So when do we go class level, and when not?
 
Pauline McNamara
Sheriff
Posts: 4012
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oops, forgot to add that the context is that nasty old Say-4b assignment.
[ July 25, 2005: Message edited by: Pauline McNamara ]
 
Marilyn de Queiroz
Sheriff
Posts: 9059
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Looking at section 1.3 - Class Member Ordering, I see that "final attributes" are at the top of the class and methods are at the bottom.

It's always best to declare constants at the top of your class. Defining constants inside your methods is a bad practice.

I guess you're looking at section 3.3 - Initialization, where I see "Try to not declare a variable until just before it is used unless it will impact the performance of the code." The JVM deals with constants at compile time and other variables at run-time.
[ July 25, 2005: Message edited by: Marilyn de Queiroz ]
 
Joyce Lee
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As mentioned earlier, it's more appropriate to declare constants at the top of a class instead of inside a method. By declaring a variable final means its value cannot be modified once it's assigned. A static variable is only created once per class during loading. A local variable of a method is created each time the method is invoked. See also VM specification: 2.5 Variables for details.

So what is the difference between the following two declarations?


In approach 1, the variable ONE is only created once when the Test class is loaded because it's declared as static. As it's final, the value cannot be changed once it's assigned.

In approach 2, a (local) variable ONE is created each time aMethod is invoked. As it's final, a value can only be assigned once to ONE inside aMethod().

As we can see, the obvious difference is the way variable ONE is created in both approaches.
[ July 30, 2005: Message edited by: Joyce Lee ]
 
Layne Lund
Ranch Hand
Posts: 3061
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Joyce Lee:
As mentioned earlier, it's more appropriate to declare constants at the top of a class instead of inside a method. By declaring a variable final means its value cannot be modified once it's assigned. A static variable is only created once per class during loading. A local variable of a method is created each time the method is invoked. See also VM specification: 2.5 Variables for details.

So what is the difference between the following two declarations?


In approach 1, the variable ONE is only created once when the Test class is loaded because it's declared as static. As it's final, the value cannot be changed once it's assigned.

In approach 2, a (local) variable ONE is created each time aMethod is invoked. As it's final, a value can only be assigned once to ONE inside aMethod().

As we can see, the obvious difference is the way variable ONE is created in both approaches.

[ July 30, 2005: Message edited by: Joyce Lee ]


If the compiler is smart, it won't create either variable at run time. Since they are both marked final and have an initial value, the compiler can optimize away the variable and use a literal constant in the byte code. The compiler shouldn't allocate any memory for a variable in either case.

I don't know that this is the way it actually works, but it seems like an easy optimization to implement in the compiler. So this means that the only benefit we get from declaring class-level constants is for readability.

Layne
 
Joyce Lee
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Layne]:If the compiler is smart, it won't create either variable at run time. Since they are both marked final and have an initial value, the compiler can optimize away the variable and use a literal constant in the byte code. The compiler shouldn't allocate any memory for a variable in either case.

I don't know that this is the way it actually works, but it seems like an easy optimization to implement in the compiler. So this means that the only benefit we get from declaring class-level constants is for readability.


Indeed, the JDK's compiler replaces the ONE with 1 since it's final and is initialized with a int literal. In this case, the performance may not be an issue. The question is, is this optimization a guarantee on every compiler? If so, why declaring class-level constant is more readable than at method-level? Any comment is welcome!
[ July 31, 2005: Message edited by: Joyce Lee ]
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Layne]: If the compiler is smart, it won't create either variable at run time.

I'm pretty sure the variable will be created as a static field of the class in question (allocated in memory), however most code that uses the value will be optimized so that it inlines the value at compile-time rather than accesses the value of the field. You can see that the field still exists as a field of the class using reflection:


[Joyce]: The question is, is this optimization a guarantee on every compiler?

For fields, yes, it's guaranteed by JLS3 13.4.9: "If a field is a constant variable (�4.12.4), then deleting the keyword final or changing its value will not break compatibility with pre-existing binaries by causing them not to run, but they will not see any new value for the usage of the field unless they are recompiled." Other classes have inlined the old value; they won't see the new value. As usual, reflection is sort of outside the JLS rules, as the passage quoted doesn't take reflection into account as a possible way to "see" the value of a field.

For a constant local variable, I don't know that there's any clear guarantee that all uses of the variable will be inlined with the value of the constant, as this doesn't really create a clear observable effect. (There's no way to recompile the variable without recompiling the method that uses it.) There are other effects that depend on whether the variable is constant or not, but I don't think they will tell us whether the value has necessarily been inlined. I suspect that yes it has been inlined, but I don't think there's a guarantee for a local variable. Not sure it really matters.

[Joyce]: If so, why declaring class-level constant is more readable than at method-level?

I'm not convinced it is. If the constant is only used in one method, I'm inclined to define it where it's used, locally. One possible reason to put it at class level is because that's where come other people may expect to find it, and following expectations is usually a good thing in collaborative development. If indeed it's a reasonably well-established expectation, and I don't think this one is. Some people might expect it to be local, and others class level.

If the constant is defined within a method, then regardless of expectations, it's going to be pretty obvious where to find it, since the only time you care about it is when you're looking at that method, and it's defined right there. (This assumes you keep your methods short enough to easily see the whole thing onscreen at one time, a principle that I think is a lot more important than where you declare a constant which is only used in one method.) And when reading the method - if you don't notice the declaration, how would you know it's a constant anyway? (If only there were some standard, well-established way of indicating a constant simply by the variable name.) Any given variable you may encounter may be local, or class/instance level. If you can't tell from the name which it is, then you may just have to check both places. Unless it's obvious because it's already right in front of your face, defined in the same context it's used.

Personally I don't think this matters much either way. Of course Marilyn may be able to give a better perspective on the reasoning here.
 
Marilyn de Queiroz
Sheriff
Posts: 9059
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Layne]: If the compiler is smart, it won't create either variable at run time.

I would rather not depend on the "smartness" of the compiler.

[Joyce]: If so, why declaring class-level constant is more readable than at method-level?

[Jim]: I'm not convinced it is. If the constant is only used in one method, I'm inclined to define it where it's used, locally. One possible reason to put it at class level is because that's where come other people may expect to find it, and following expectations is usually a good thing in collaborative development.

Indeed, this can be debatable.

If the constant is defined within a method, then regardless of expectations, it's going to be pretty obvious where to find it, since the only time you care about it is when you're looking at that method, and it's defined right there. (This assumes you keep your methods short enough to easily see the whole thing onscreen at one time, a principle that I think is a lot more important than where you declare a constant which is only used in one method.)

If the constant is only used once, I wonder if it really needs to be declared as a constant at all. If a variable is only used in one method, it should be declared as close as possible to where it is first used.


Ignoring the separate issue of whether a constant should be in all CAPS as the Sun Style Guide recommends or not as the Cattle Drive Style Guide demands , I agree with Jim that keeping methods short is important. In this particular case (Assignment 4-Say), where you are declaring an array (or two or three) which is relatively lengthy, moving the constant(s) outside the method helps keep the method shorter and more readable.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, are we talking about an array? (Or two or three?) In that case, all the discussion of inlined constants is irrelevant, as arrays are not compile-time constants. Only primitives and Strings can be compile-time constants. All other objects are necessarily created at runtime. So a locally declared array would be instantiated each time a method is invoked. Which would be a good reason to declare it at class level instead.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic