Global variables are never necessary unless you are interfacing with existing code that imposes unsuitable constraints.
One alternative is to make the dependency explicit:
1. Create a class that describes the purpose of this shared data. Without knowing your problem domain, I'm going to call it a Counter
.
class Counter {
private int value = 0;
public void incrementBy(int x) {
if (x < 0)
throw IllegalArgumentException("must increment by non-negative value");
value += x;
}
public int get() { return value; }
}
Note that wrapping the variable through accessor functions allows us to impose checks and constraints. This lack of checks is one major problem with exposing variables directly.
2. Use some dependency injection mechanism to supply a Counter
instance to all classes that need it. For example, we can use constructor injection:
public class ClassName2 {
private Counter counter;
public ClassName2(Counter counter) {
this.counter = counter;
}
public void meth(){
counter.incrementBy(4);
}
}
The counter is created in some initialization code (like your main() function) and then provided when the dependent classes are instantiated:
Counter counter = new Counter();
ClassName instance = new ClassName(counter);
ClassName2 instance2 = new ClassName2(counter);
All global variables have a similar instantiation, but it's just done implicitly during class loading. By managing the initialization ourselves we gain a lot of flexibility:
- we can supply a different Counter class during testing.
- we are able use multiple Counter instances if different parts of the code are not supposed to share a Counter, for example when the original
ClassName
functionality is reused in a different context.
If you cannot make these dependencies explicit, at least encapsulate the variable using static methods in a similar fashion.