Iterating and counting across class variables in Java - java

I have class, which contains variables of multiple type, most of those (about 30) are double:
String something;
double x;
double y;
double z;
...
I want to iterate over doubles, but also keep them written in this "classic way", not inside array, because derived classes use most of them. The function I am having problem with now is how to iterate across all the double type variables, find how many of those are non zero and then pick one of all these variables randomly. There will be thousands of instances of this class and as I said, there are classes that expand this one. So I am working on solution, preferably something like pseudo:
nonzeros = 0
foreach doubleVarInClass variable
{
if (variable != 0)
nonzeros++;
}
if (nonzeros < parameter)
{
randomDoubleVarInClass = random.next(...);
}
One solution which I was thinking about was to use HashMap to keep all the variables in, but then I will have to rewrite all classes that uses this one and not sure how it will affect performance, since it will be pretty intensively used all the time. Should I be afraid of performance and try something with classic arrays perhaps? I'd like to atleast keep variable names if nothing. I thought about array with references to these variables, so I can keep them written this way, not sure if its possible due to value passing in Java.
Also maybe there is some structure that keeps info about how many of those are non zero or have efficient function for it?
Thank you for any info that could solve my problem :)

I suggest using reflection for this. Suppose you have instance of your class named o:
int nonzeros = 0;
for (Field f : o.getClass().getDeclaredFields()) {
f.setAccessible(true);
if (f.getType().equals(Double.TYPE) && f.getDouble(o) != 0.0) {
nonzeros++;
}
}
NOTE: Java Reflection will probably be bad idea from the point of performance, and you should test this first, from that point of view. Besides that, this provide easy checks without any changes in your class definition. In Java 6 performance of reflection is little better than on older versions, and you should check this in your personal use case and in your environment.

Related

Is defining variables for every condition is better then using getter and setters?

I have two codes can anyone tell me which approach is the better and why.
Approach 1 -
if (("Male").equalsIgnoreCase(input.getSex()) || ("Female").equalsIgnoreCase(input.getSex())) {
// do something
}else{
//do somethong
}
Approach 2 -
String tempSex = input.getSex()
if (("Male").equalsIgnoreCase(tempSex) || ("Female").equalsIgnoreCase(tempSex)) {
// do something
}else{
//do somethong
}
this is one condition, in my code, I have a lot of conditions similar to this one. In some condition, I have to compare with a lot more Strings.
Is this a good approach to define variables for every condition or I can use getter and setters?
These two approaches are essentially identical in terms of performance assuming the getSex function is a trivial getter (if getSex is complex or involves changing some other state in the class then these two bits of code are NOT equivalent).
I would prefer the first from a style point of view in that the extra local variable is slightly confusing to the flow of the code.
However if you main purpose is using code of this form is to validate legal input (as it appears from your example) I would try to create a method
boolean input.isSexValid() to encapsulate that functionality which would make the code less repetitive and more readable.
Strong argument that this is primarily opinion based, but:
I vote Approach 2.
What if the getter is slow (like it has to go to a DB)? You have a redundant round trip to the DB.

Ways to avoid passing-by-reference in Java

This question is probably as old as the hills. Nevertheless, after reading lots of articles and forums I still don't see a good solution to my problem.
I have to transfer some Monte Carlo simulation programs from C++ to Java. The problem is that it heavily relies on passing variables by reference in functions, like:
void make_step(int &a, int &b, double &c) {
a++;
b += a;
c *= 1.1;
}
There is no passing by reference in Java, as well as possible analogs, like multiple return values or nested functions. Solutions, which I have read on this site, usually involve encapsulation of primitive types into objects. Alternatively - break functions to single-return ones. However, in my case it results in too long and complicated code (few lines of C++ code grow to almost pages in Java). Also, since these algorithms are hard to debug, I want to avoid dramatical changes in code while porting.
What I do now is substituting of all primitive type variables with arrays of length 1 (which are objects and can be modified inside functions). But it doesn't look like very elegant solutions. Does anyone have better ideas?
If you want the parameters to be "in-out" variables, they have to be object references.
With Mutable Wrappers
You can use mutable wrappers but this will require you to slightly modify your existing code (the algorithm):
class Int {
int v;
}
class MDouble {
double v;
}
void make_step(Int a, Int b, MDouble c) {
a.v++;
b.v += a.v;
c.v *= 1.1;
}
With Local Variable Copies
If you want to keep your original code, you can create local variable copies of the wrapped parameters, and you can use those without having to modify your code.
At the end of your method (before return) copy back the local variables into the wrappers and you're done. A tip for this is to use a try-finally block so your local variables will get copied back into the wrappers no matter how or where your method returns:
void make_step(int[] aa, int[] bb, double[] cc) {
int a = aa[0];
int b = bb[0];
double c = cc[0];
try {
// all your original code comes here
a++;
b += a;
c *= 1.1;
} finally {
aa[0] = a;
bb[0] = b;
cc[0] = c;
}
}
There are few options:
Wrap all parameters in an object. The simple version indeed makes the program longer, but if you can wrap the entire algorithm in an object then those parameters become the object members.
Use mutable integers (objects) - either Java's AtomicInteger which has get()/set() methods, or the commnos-lang version
There are mutable Integer and Decimal classes out there you can use those to pass by reference. Check out Apache Commons libraries here
When writing same logic from c++ to java
Rely more on .equals and comparators over == >< for comparisions
Use member variables and for local variable return the updated objects back to the called methods to get the changes.
You can use "atomic references" to wrap your object in a reference.
There are atomicXXX classes for most basic types as well. These will work similarly to normal references aside from the overhead of creating them in the first place.
Arrays of length 1 are just as a solution, but if you dislike the syntax or appearance of them, this is the only other solution that I know of that can mimic the same behavior without a general refactor.

java: combined instanceof and cast?

(Please no advise that I should abstract X more and add another method to it.)
In C++, when I have a variable x of type X* and I want to do something specific if it is also of type Y* (Y being a subclass of X), I am writing this:
if(Y* y = dynamic_cast<Y*>(x)) {
// now do sth with y
}
The same thing seems not possible in Java (or is it?).
I have read this Java code instead:
if(x instanceof Y) {
Y y = (Y) x;
// ...
}
Sometimes, when you don't have a variable x but it is a more complex expression instead, just because of this issue, you need a dummy variable in Java:
X x = something();
if(x instanceof Y) {
Y y = (Y) x;
// ...
}
// x not needed here anymore
(Common thing is that something() is iterator.next(). And there you see that you also cannot really call that just twice. You really need the dummy variable.)
You don't really need x at all here -- you just have it because you cannot do the instanceof check at once with the cast. Compare that again to the quite common C++ code:
if(Y* y = dynamic_cast<Y*>( something() )) {
// ...
}
Because of this, I have introduced a castOrNull function which makes it possible to avoid the dummy variable x. I can write this now:
Y y = castOrNull( something(), Y.class );
if(y != null) {
// ...
}
Implementation of castOrNull:
public static <T> T castOrNull(Object obj, Class<T> clazz) {
try {
return clazz.cast(obj);
} catch (ClassCastException exc) {
return null;
}
}
Now, I was told that using this castOrNull function in that way is an evil thing do to. Why is that? (Or to put the question more general: Would you agree and also think this is evil? If yes, why so? Or do you think this is a valid (maybe rare) use case?)
As said, I don't want a discussion whether the usage of such downcast is a good idea at all. But let me clarify shortly why I sometimes use it:
Sometimes I get into the case where I have to choose between adding another new method for a very specific thing (which will only apply for one single subclass in one specific case) or using such instanceof check. Basically, I have the choice between adding a function doSomethingVeryVerySpecificIfIAmY() or doing the instanceof check. And in such cases, I feel that the latter is more clean.
Sometimes I have a collection of some interface / base class and for all entries of type Y, I want to do something and then remove them from the collection. (E.g. I had the case where I had a tree structure and I wanted to delete all childs which are empty leafs.)
Starting Java 14 you should be able to do instanceof and cast at the same time. See https://openjdk.java.net/jeps/305.
Code example:
if (obj instanceof String s) {
// can use s here
} else {
// can't use s here
}
The variable s in the above example is defined if instanceof evaluates to true. The scope of the variable depends on the context. See the link above for more examples.
Now, I was told that using this castOrNull function in that way is an evil thing do to. Why is that?
I can think of a couple of reasons:
It is an obscure and tricky way of doing something very simple. Obscure and tricky code is hard to read, hard to maintain, a potential source of errors (when someone doesn't understand it) and therefore evil.
The obscure and tricky way that the castOrNull method works most likely cannot be optimized by the JIT compiler. You'll end up with at least 3 extra method calls, plus lots of extra code to do the type check and cast reflectively. Unnecessary use of reflection is evil.
(By contrast, the simple way (with instanceof followed by a class cast) uses specific bytecodes for instanceof and class casting. The bytecode sequences can almost certainly will be optimized so that there is no more than one null check and no more that one test of the object's type in the native code. This is a common pattern that should be easy for the JIT compiler to detect and optimize.)
Of course, "evil" is just another way of saying that you REALLY shouldn't do this.
Neither of your two added examples, make use of a castOrNull method either necessary or desirable. IMO, the "simple way" is better from both the readability and performance perspectives.
In most well written/designed Java code the use of instanceof and casts never happens. With the addition of generics many cases of casts (and thus instanceof) are not needed. They do, on occasion still occur.
The castOrNull method is evil in that you are making Java code look "unnatural". The biggest problem when changing from one language to another is adopting the conventions of the new language. Temporary variables are just fine in Java. In fact all your method is doing is really hiding the temporary variable.
If you are finding that you are writing a lot of casts you should examine your code and see why and look for ways to remove them. For example, in the case that you mention adding a "getNumberOfChildren" method would allow you to check if a node is empty and thus able to prune it without casting (that is a guess, it might not work for you in this case).
Generally speaking casts are "evil" in Java because they are usually not needed. Your method is more "evil" because it is not written in the way most people would expect Java to be written.
That being said, if you want to do it, go for it. It isn't actually "evil" just not "right" way to do it in Java.
IMHO your castOrNull is not evil, just pointless. You seem to be obsessed with getting rid of a temporary variable and one line of code, while to me the bigger question is why you need so many downcasts in your code? In OO this is almost always a symptom of suboptimal design. And I would prefer solving the root cause instead of treating the symptom.
I don't know exactly why the person said that it was evil. However one possibility for their reasoning was the fact that you were catching an exception afterwards rather than checking before you casted. This is a way to do that.
public static <T> T castOrNull(Object obj, Class<T> clazz) {
if ( clazz.isAssignableFrom(obj.getClass()) ) {
return clazz.cast(obj);
} else {
return null;
}
}
Java Exceptions are slow. If you're trying to optimize your performance by avoiding a double cast, you're shooting yourself in the foot by using exceptions in lieu of logic. Never rely on catching an exception for something you could reasonably check for and correct for (exactly what you're doing).
How slow are Java exceptions?

Java instance variables vs. local variables

I'm in my first programming class in high school. We're doing our end of the first semester project.
This project only involves one class, but many methods. My question is about best practice with instance variables and local variables. It seems that it would be much easier for me to code using almost only instance variables. But I'm not sure if this is how I should be doing it or if I should be using local variables more (I would just have to have methods take in the values of local variables a lot more).
My reasoning for this is also because a lot of times I'll want to have a method return two or three values, but this is of course not possible. Thus it just seems easier to simply use instance variables and never having to worry since they are universal in the class.
I haven't seen anyone discuss this so I'll throw in more food for thought. The short answer/advice is don't use instance variables over local variables just because you think they are easier to return values. You are going to make working with your code very very hard if you don't use local variables and instance variables appropriately. You will produce some serious bugs that are really hard to track down. If you want to understand what I mean by serious bugs, and what that might look like read on.
Let's try and use only instance variables as you suggest to write to functions. I'll create a very simple class:
public class BadIdea {
public Enum Color { GREEN, RED, BLUE, PURPLE };
public Color[] map = new Colors[] {
Color.GREEN,
Color.GREEN,
Color.RED,
Color.BLUE,
Color.PURPLE,
Color.RED,
Color.PURPLE };
List<Integer> indexes = new ArrayList<Integer>();
public int counter = 0;
public int index = 0;
public void findColor( Color value ) {
indexes.clear();
for( index = 0; index < map.length; index++ ) {
if( map[index] == value ) {
indexes.add( index );
counter++;
}
}
}
public void findOppositeColors( Color value ) {
indexes.clear();
for( index = 0; i < index < map.length; index++ ) {
if( map[index] != value ) {
indexes.add( index );
counter++;
}
}
}
}
This is a silly program I know, but we can use it to illustrate the concept that using instance variables for things like this is a tremendously bad idea. The biggest thing you'll find is that those methods use all of the instance variables we have. And it modifies indexes, counter, and index every time they are called. The first problem you'll find is that calling those methods one after the other can modify the answers from prior runs. So for example, if you wrote the following code:
BadIdea idea = new BadIdea();
idea.findColor( Color.RED );
idea.findColor( Color.GREEN ); // whoops we just lost the results from finding all Color.RED
Since findColor uses instance variables to track returned values we can only return one result at a time. Let's try and save off a reference to those results before we call it again:
BadIdea idea = new BadIdea();
idea.findColor( Color.RED );
List<Integer> redPositions = idea.indexes;
int redCount = idea.counter;
idea.findColor( Color.GREEN ); // this causes red positions to be lost! (i.e. idea.indexes.clear()
List<Integer> greenPositions = idea.indexes;
int greenCount = idea.counter;
In this second example we saved the red positions on the 3rd line, but same thing happened!?Why did we lose them?! Because idea.indexes was cleared instead of allocated so there can only be one answer used at a time. You have to completely finish using that result before calling it again. Once you call a method again the results are cleared and you lose everything. In order to fix this you'll have to allocate a new result each time so red and green answers are separate. So let's clone our answers to create new copies of things:
BadIdea idea = new BadIdea();
idea.findColor( Color.RED );
List<Integer> redPositions = idea.indexes.clone();
int redCount = idea.counter;
idea.findColor( Color.GREEN );
List<Integer> greenPositions = idea.indexes.clone();
int greenCount = idea.counter;
Ok finally we have two separate results. The results of red and green are now separate. But, we had to know a lot about how BadIdea operated internally before the program worked didn't we? We need to remember to clone the returns every time we called it to safely make sure our results didn't get clobbered. Why is the caller forced to remember these details? Wouldn't it be easier if we didn't have to do that?
Also notice that the caller has to use local variables to remember the results so while you didn't use local variables in the methods of BadIdea the caller has to use them to remember results. So what did you really accomplish? You really just moved the problem to the caller forcing them to do more. And the work you pushed onto the caller is not an easy rule to follow because there are some many exceptions to the rule.
Now let's try doing that with two different methods. Notice how I've been "smart" and I reused those same instance variables to "save memory" and kept the code compact. ;-)
BadIdea idea = new BadIdea();
idea.findColor( Color.RED );
List<Integer> redPositions = idea.indexes;
int redCount = idea.counter;
idea.findOppositeColors( Color.RED ); // this causes red positions to be lost again!!
List<Integer> greenPositions = idea.indexes;
int greenCount = idea.counter;
Same thing happened! Damn but I was being so "smart" and saving memory and the code uses less resources!!! This is the real peril of using instance variables like this is calling methods is order dependent now. If I change the order of the method calls the results are different even though I haven't really changed the underlying state of BadIdea. I didn't change the contents of the map. Why does the program yield different results when I call the methods in different order?
idea.findColor( Color.RED )
idea.findOppositeColors( Color.RED )
Produces a different result than if I swapped those two methods:
idea.findOppositeColors( Color.RED )
idea.findColor( Color.RED )
These types of errors are really hard to track down especially when those lines aren't right next to each other. You can completely break your program by just adding a new call in anywhere between those two lines and get wildly different results. Sure when we're dealing with small number of lines it's easy to spot errors. But, in a larger program you can waste days trying to reproduce them even though the data in the program hasn't changed.
And this only looks at single threaded problems. If BadIdea was being used in a multi-threaded situation the errors can get really bizarre. What happens if findColors() and findOppositeColors() is called at the same time? Crash, all your hair falls out, Death, space and time collapse into a singularity and the universe is swallows up? Probably at least two of those. Threads are probably above your head now, but hopefully we can steer you away from doing bad things now so when you do get to threads those bad practices don't cause you real heartache.
Did you notice how careful you had to be when calling the methods? They overwrote each other, they shared memory possibly randomly, you had to remember the details of how it worked on the inside to make it work on the outside, changing the order in which things were called produce very big changes in the next lines down, and it only could only work in a single thread situation. Doing things like this will produce really brittle code that seems to fall apart whenever you touch it. These practices I showed contributed directly to the code being brittle.
While this might look like encapsulation it is the exact opposite because the technical details of how you wrote it have to be known to the caller. The caller has to write their code in a very particular way to make their code work, and they can't do it without knowing about the technical details of your code. This is often called a Leaky Abstraction because the class is suppose to hide the technical details behind an abstraction/interface, but the technical details leak out forcing the caller to change their behavior. Every solution has some degree of leaky-ness, but using any of the above techniques like these guarantees no matter what problem you are trying to solve it will be terribly leaky if you apply them. So let's look at the GoodIdea now.
Let's rewrite using local variables:
public class GoodIdea {
...
public List<Integer> findColor( Color value ) {
List<Integer> results = new ArrayList<Integer>();
for( int i = 0; i < map.length; i++ ) {
if( map[index] == value ) {
results.add( i );
}
}
return results;
}
public List<Integer> findOppositeColors( Color value ) {
List<Integer> results = new ArrayList<Integer>();
for( int i = 0; i < map.length; i++ ) {
if( map[index] != value ) {
results.add( i );
}
}
return results;
}
}
This fixes every problem we discussed above. I know I'm not keeping track of counter or returning it, but if I did I can create a new class and return that instead of List. Sometimes I use the following object to return multiple results quickly:
public class Pair<K,T> {
public K first;
public T second;
public Pair( K first, T second ) {
this.first = first;
this.second = second;
}
}
Long answer, but a very important topic.
Use instance variables when it's a core concept of your class. If you're iterating, recursing or doing some processing, then use local variables.
When you need to use two (or more) variables in the same places, it's time to create a new class with those attributes (and appropriate means to set them). This will make your code cleaner and help you think about problems (each class is a new term in your vocabulary).
One variable may be made a class when it is a core concept. For example real-world identifiers: these could be represented as Strings, but often, if you encapsulate them into their own object they suddenly start "attracting" functionality (validation, association to other objects, etc.)
Also (not entirely related) is object consistency - an object is able to ensure that its state makes sense. Setting one property may alter another. It also makes it far easier to alter your program to be thread-safe later (if required).
Local variables internal to methods are always prefered, since you want to keep each variable's scope as small as possible. But if more than one method needs to access a variable, then it's going to have to be an instance variable.
Local variables are more like intermediate values used to reach a result or compute something on the fly. Instance variables are more like attributes of a class, like your age or name.
The easy way: if the variable must be shared by more than one method, use instance variable, otherwise use local variable.
However, the good practice is to use as more local variables as possible. Why? For your simple project with only one class, there is no difference. For a project that includes a lot of classes, there is big difference. The instance variable indicates the state of your class. The more instance variables in your class, the more states this class can have and then, the more complex this class is, the hard the class is maintained or the more error prone your project might be. So the good practice is to use as more local variable as possible to keep the state of the class as simple as possible.
Short story: if and only if a variable needs to be accessed by more than one method (or outside of the class), create it as an instance variables. If you need it only locally, in a single method, it has to be a local variable.
Instance variables are more costly than local variables.
Keep in mind: instance variables are initialized to default values while local variables are not.
Declare variables to be scoped as narrowly as possible. Declare local variables first. If this isn't sufficient, use instance variables. If this isn't sufficient, use class (static) variables.
I you need to return more than one value return a composite structure, like an array or an object.
Try to think about your problem in terms of objects. Each class represents a different type of object. Instance variables are the pieces of data that a class needs to remember in order to work, either with itself or with other objects. Local variables should just be used intermediate calculations, data that you don't need to save once you leave the method.
Try not to return more than one value from your methods in first place. If you can't, and in some cases you really can't, then I would recommend encapsulating that in a class. Just in last case I would recommend changing another variable inside your class (an instance variable). The problem with the instance variables approach is that it increases side effects - for example, you call method A in your program and it modifies some instance(s) variable(s). Over time, that leads to increased complexity in your code and maintenance becomes harder and harder.
When I have to use instance variables, I try to make then final and initialize then in the class constructors, so side effects are minimized. This programming style (minimizing the state changes in your application) should lead to better code that is easier to maintain.
Generally variables should have minimal scope.
Unfortunately, in order to build classes with minimized variable scope, one often needs to do a lot of method parameter passing.
But if you follow that advice all the time, perfectly minimizing variable scope, you
may end up with a lot of redundancy and method inflexibility with all the required objects passed in and out of methods.
Picture a code base with thousands of methods like this:
private ClassThatHoldsReturnInfo foo(OneReallyBigClassThatHoldsCertainThings big,
AnotherClassThatDoesLittle little) {
LocalClassObjectJustUsedHere here;
...
}
private ClassThatHoldsReturnInfo bar(OneMediumSizedClassThatHoldsCertainThings medium,
AnotherClassThatDoesLittle little) {
...
}
And, on the other hand, imagine a code base with lots of instance variables like this:
private OneReallyBigClassThatHoldsCertainThings big;
private OneMediumSizedClassThatHoldsCertainThings medium;
private AnotherClassThatDoesLittle little;
private ClassThatHoldsReturnInfo ret;
private void foo() {
LocalClassObjectJustUsedHere here;
....
}
private void bar() {
....
}
As code increases, the first way may minimize variable scope best, but can easily lead to a lot of method parameters being passed around. The code will usually be more verbose and this can lead to a complexity as one refactors all these methods.
Using more instance variables can reduce the complexity of lots of method parameters being passed around and can give a flexibility to methods when you are frequently reorganizing methods for clarity. But it creates more object state that you have to maintain. Generally the advice is to do the former and refrain from the latter.
However, very often, and it may depend on the person, one can more easily manage state complexity compared with the thousands of extra object references of the first case. One may notice this when business logic within methods increases and organization needs to change to keep order and clarity.
Not only that. When you reorganize your methods to keep clarity and make lots of method parameter changes in the process, you end up with lots of version control diffs which is not so good for stable production quality code. There is a balance. One way causes one kind of complexity. The other way causes another kind of complexity.
Use the way that works best for you. You will find that balance over time.
I think this young programmer has some insightful first impressions for low maintenance code.
Use instance variables when
If two functions in the class need the same value, then make it an instance variable
or
If the state is not expected to change, make it an instance variable. For example: immutable object, DTO, LinkedList, those with final variables
or
If it is an underlying data on whom actions are performed. For example: final in arr[] in the PriorityQueue.java source code file
or
Even if it is used only once and state is expected to change, make it an instance if it is used only once by a function whose parameter list should be empty. For example: HTTPCookie.java Line: 860 hashcode() function uses 'path variable'.
Similarly, use a local variable when none of these conditions match, specifically if the role of the variable would end after the stack is popped off. For example: Comparator.compare(o1, o2);

In Java, should variables be declared at the top of a function, or as they're needed?

I'm cleaning up Java code for someone who starts their functions by declaring all variables up top, and initializing them to null/0/whatever, as opposed to declaring them as they're needed later on.
What are the specific guidelines for this? Are there optimization reasons for one way or the other, or is one way just good practice? Are there any cases where it's acceptable to deviate from whatever the proper way of doing it is?
Declare variables as close to the first spot that you use them as possible. It's not really anything to do with efficiency, but makes your code much more readable. The closer a variable is declared to where it is used, the less scrolling/searching you have to do when reading the code later. Declaring variables closer to the first spot they're used will also naturally narrow their scope.
The proper way is to declare variables exactly when they are first used and minimize their scope in order to make the code easier to understand.
Declaring variables at the top of functions is a holdover from C (where it was required), and has absolutely no advantages (variable scope exists only in the source code, in the byte code all local variables exist in sequence on the stack anyway). Just don't do it, ever.
Some people may try to defend the practice by claiming that it is "neater", but any need to "organize" code within a method is usually a strong indication that the method is simply too long.
From the Java Code Conventions, Chapter 6 on Declarations:
6.3 Placement
Put declarations only at the beginning
of blocks. (A block is any code
surrounded by curly braces "{" and
"}".) Don't wait to declare variables
until their first use; it can confuse
the unwary programmer and hamper code
portability within the scope.
void myMethod() {
int int1 = 0; // beginning of method block
if (condition) {
int int2 = 0; // beginning of "if" block
...
}
}
The one exception to the rule is
indexes of for loops, which in Java
can be declared in the for statement:
for (int i = 0; i < maxLoops; i++) { ... }
Avoid local declarations that hide
declarations at higher levels. For
example, do not declare the same
variable name in an inner block:
int count;
...
myMethod() {
if (condition) {
int count = 0; // AVOID!
...
}
...
}
If you have a kabillion variables used in various isolated places down inside the body of a function, your function is too big.
If your function is a comfortably understandable size, there's no difference between "all up front" and "just as needed".
The only not-up-front variable would be in the body of a for statement.
for( Iterator i= someObject.iterator(); i.hasNext(); )
From Google Java Style Guide:
4.8.2.2 Declared when needed
Local variables are not habitually declared at the start of their
containing block or block-like construct. Instead, local variables are
declared close to the point they are first used (within reason), to
minimize their scope. Local variable declarations typically have
initializers, or are initialized immediately after declaration.
Well, I'd follow what Google does, on a superficial level it might seem that declaring all variables at the top of the method/function would be "neater", it's quite apparent that it'd be beneficial to declare variables as necessary. It's subjective though, whatever feels intuitive to you.
I've found that declaring them as-needed results in fewer mistakes than declaring them at the beginning. I've also found that declaring them at the minimum scope possible to also prevent mistakes.
When I looked at the byte-code generated by the location of the declaration few years ago, I found they were more-or-less identical. There were ocassionally differences depending on when they were assigned. Even something like:
for(Object o : list) {
Object temp = ...; //was not "redeclared" every loop iteration
}
vs
Object temp;
for(Object o : list) {
temp = ...; //nearly identical bytecoode, if not exactly identical.
}
Came out more or less identical
I am doing this very same thing at the moment. All of the variables in the code that I am reworking are declared at the top of the function. I've seen as I've been looking through this that several variables are declared but NEVER used or they are declared and operations are being done with them (ie parsing a String and then setting a Calendar object with the date/time values from the string) but then the resulting Calendar object is NEVER used.
I am going through and cleaning these up by taking the declarations from the top and moving them down in the function to a spot closer to where it is used.
Defining variable in a wider scope than needed hinders understandability quite a bit. Limited scope signals that this variable has meaning for only this small block of code and you can not think about when reading further. This is a pretty important issue because of the tiny short-term working memory that the brain has (it said that on average you can keep track of only 7 things). One less thing to keep track of is significant.
Similarly you really should try to avoid variables in the literal sense. Try to assign all things once, and declare them final so this is known to the reader. Not having to keep track whether something changes or not really cuts the cognitive load.
Principle: Place local variable declarations as close to their first use as possible, and NOT simply at the top of a method. Consider this example:
/** Return true iff s is a blah or a blub. */
public boolean checkB(String s) {
// Return true if s is a blah
... code to return true if s is a blah ...
// Return true if s is a blub. */
int helpblub= s.length() + 1;
... rest of code to return true is s is a blah.
return false;
}
Here, local variable helpblub is placed where it is necessary, in the code to test whether s is a blub. It is part of the code that implements "Return true is s is a blub".
It makes absolutely no logical sense to put the declaration of helpblub as the first statement of the method. The poor reader would wonder, why is that variable there? What is it for?
I think it is actually objectively provable that the declare-at-the-top style is more error-prone.
If you mutate-test code in either style by moving lines around at random (to simulate a merge gone bad or someone unthinkingly cut+pasting), then the declare-at-the-top style has a greater chance of compiling while functionally wrong.
I don't think declare-at-the-top has any corresponding advantage that doesn't come down to personal preference.
So assuming you want to write reliable code, learn to prefer doing just-in-time declaration.
Its a matter of readability and personal preference rather than performance. The compiler does not care and will generate the same code anyway.
I've seen people declare at the top and at the bottom of functions. I prefer the top, where I can see them quickly. It's a matter of choice and preference.

Categories