Coding in Java - replacement for a global variable

  • Java
  • Thread starter Borek
  • Start date
  • #1
Borek
Mentor
28,540
2,976
I was forced into learning Java. I feel reasonably fluent in C++, so the main problem is with the differences between the way languages are designed.

There are no global variables in Java. However, I need one - or at least some equivalent. I have something like a database object that I want to have access to in many classes in my program. In C++ I would just make it a global variable. In Java I can't. ATM I can think of three ways of dealing with the situation:

1. Make the object a static variable in my main class. I feel like it's a hack, not a serious solution.

2. Define all my classes inside of the main class. Inconvenient nonsense.

3. Pass the object to all methods that may need an access to it, or at least pass it to constructors, so that every object can save a local reference to the database object. Makes the code bloated, or/and it means I need to add constructors even in all places were otherwise default would be enough.

Other ideas? Or perhaps I am approaching it completely wrong, and that's just not the way you program in Java?
 

Answers and Replies

  • #2
AlephZero
Science Advisor
Homework Helper
6,994
291
You don't need to put the static variables in the main class. You can create a class (or classes) that only contain static variables.
Code:
public class FooData
{
  public static int bar = 5;
}
And then reference FooData.bar wherever you need it. You can declare the variable final if you want the value to be read-only.

If you want to stop yourself "accidentally" referencing a global, you can put them in an interface:
Code:
public interface FooData
{
  int bar = 5;
}

public class MyClass implements FooData
{
  int bar2 = bar * 2;
}
The style Java police don't like that idea. You only have to type bar instead of FooData.bar, but you might forget what other global variables are declared in the interface and use one when you should have declared a local variable.

The style police would probably say that if your classes are properly designed, you don't need "global" data anyway - you only need static variables that are internal to the class that uses them. (But in C++ you are not forced to use OOP if you don't want to, of course).
 
Last edited:
  • Like
Likes 1 person
  • #3
Borek
Mentor
28,540
2,976
You don't need to put the static variables in the main class. You can create a class (or classes) that only contain static variables.
Thanks, that's a solution I didn't thought of.

The style police would probably say that if your classes are properly designed, you don't need "global" data anyway - you only need static variables that are internal to the class that uses them.
Something to think about! Could be that's what I am missing.
 
  • #4
191
3
I'm not the greatest OO designer, but in this situation I just make a database class that handles it all, with a runQuery(myQuery) method that returns the query results to me in list. When another class needs database, I instantiate the database class and call runQuery(myQuery).
 
  • #5
Borek
Mentor
28,540
2,976
I thought about it, but IMHO it is another overkill - to use the full blown database for just a few elements. Instantiating the database class every time I need to access the data requires time & resources. The style police is perhaps happy, but the efficiency police is planning a raid to shut down the (wastefull code) base.

In general I have a feeling Java is designed in such a way it promotes inefficient coding. But let's not go there...

Edit: besides, by using an external database I would just trick myself into thinking "I solved the problem without using a global variable". No, I just used a disguised global variable called "ExternalDatabase".
 
Last edited:
  • #6
AlephZero
Science Advisor
Homework Helper
6,994
291
if your classes are properly designed, you don't need "global" data anyway - you only need static variables that are internal to the class that uses them.
Something to think about! Could be that's what I am missing.
Inheritance is useful here. Actually, the Java syntax for inheritance uses a word that gives a good clue - "extends".

You can make a base class that contains "global" data and no methods, and "extend" it to derived classes that define methods. The derived classes don't need to have anything in common except for accessing the shared data. You don't have to use virtual methods, polymorphism, etc, in the derived classes!
 
  • #7
DavidSnider
Gold Member
488
131
The design pattern for this is called a 'singleton'.
 
  • Like
Likes 1 person
  • #8
191
3
Indeed.

Like this:

Code:
class DatabaseClass {
   private static DatabaseClass databaseInstance = null;

   private DatabaseClass() {
   }

   public static DatabaseClass getInstance() {
      if(databaseInstance == null) {
         databaseInstance = new DatabaseClass();
      }
      return databaseInstance ;
   }

   public String someOtherDatabaseMethod(String param) {
      // run query or something
   }
}
You can't instantiate the class with it's (private) constructor, you can just call the static method DatabaseClass.getInstance() anytime you need it and you will get the only instance.
 
Last edited:
  • #9
Borek
Mentor
28,540
2,976
Yes, singleton is a great solution.

In a way it classifies as hack :wink:
 
  • #10
521
70
The Java equivalent of a global variable is a static member of a class. You can use a static import to make this more convenient e.g.
GlobalStuff.java
Code:
package myProg;

class GlobalStuff {
    int abc = 3;
}
MyProg.java
Code:
package myProg;
import static myProg.GlobalStuff.*;

public class MyProg {
    public static void main(String[] args) {
        System.out.println(abc);
    }
}
 
  • Like
Likes 1 person
  • #11
SixNein
Gold Member
42
16
I was forced into learning Java. I feel reasonably fluent in C++, so the main problem is with the differences between the way languages are designed.

There are no global variables in Java. However, I need one - or at least some equivalent. I have something like a database object that I want to have access to in many classes in my program. In C++ I would just make it a global variable. In Java I can't. ATM I can think of three ways of dealing with the situation:

1. Make the object a static variable in my main class. I feel like it's a hack, not a serious solution.

2. Define all my classes inside of the main class. Inconvenient nonsense.

3. Pass the object to all methods that may need an access to it, or at least pass it to constructors, so that every object can save a local reference to the database object. Makes the code bloated, or/and it means I need to add constructors even in all places were otherwise default would be enough.

Other ideas? Or perhaps I am approaching it completely wrong, and that's just not the way you program in Java?
In software engineering, global variables are bad form and should be avoided if possible even in languages like C++. Java is just a more modern language and more lessons from software engineering have been incorporated into it.

Passing a pointer to the objects is the best solution. It provides cleanly defined interfaces that communicates what the objects need. In addition, it allows data protection by keeping members private.
 
Last edited:
  • #12
Borek
Mentor
28,540
2,976
In software engineering, global variables are bad form and should be avoided if possible
As long as it doesn't interfere with the performance and readability of the code, I do my best to avoid them.

Java is just a more modern language and more lessons from software engineering have been incorporated into it.
So far I tend to disagree. It is not possible to pass variables by reference or value, only "Java style", so to write simple function to swap ints you need to do crazy tricks. That's a lesson I would prefer to forget.

Passing a pointer to the objects is the best solution. It provides cleanly defined interfaces that communicates what the objects need.
Not when the pointer has to be passed down the tree by several objects that don't need them.

But perhaps you will be able to suggest a better approach, I am open.

What I am dealing with is I have a dictionary, that contains pairs of objects, say - names of months and numbers of days. They are not constant - it may happen that the dictionary content changes, it has to be saved between program runs. I have documents, that contain objects, that need the information from the dictionary. Document itself doesn't need the data, only some of its components, and even these not always.

Where and how to store the dictionary?

In the main object, passing the pointers? That means passing pointers to documents, that would only pass them further, they don't need the information, so it is not a "cleanly defined interface that communicates what the objects need".

I can create the dictionary object each time I need the information "in situ" - but in some cases cost will be prohibitive, so IMHO it is better to have the dictionary ready and waiting, especially as it occupies a few kbytes at most.

Global variable seems a reasonable approach, even if it goes against orthodox OOP thinking.
 
  • #13
DavidSnider
Gold Member
488
131
Also look up dependency injection. It's less hacky than singletons with the same effect.
 
  • #14
DavidSnider
Gold Member
488
131
Another method is to create a factory or builder object for the parent object where you limit the number of instantiations of a dependency that its child objects require.

So:

Your main object would instantiate a FooFactory. Your FooFactory would create a single instance of MonthLookup in it's constructor, have a method Build that would create an instance of Foo and then pass the single instance of MonthLookup into the constructor of each FooChild that required it. Build would then add the FooChildren to Foo and return Foo. This way Foo doesn't need to know about MonthLookup.
 
Last edited:
  • #15
AlephZero
Science Advisor
Homework Helper
6,994
291
I think Lewis Carroll would have loved OOP.
"I could have done it in a much more complicated way," said the Red Queen, immensely proud....
 
  • #16
DavidSnider
Gold Member
488
131
Limiting scope and constraining the responsibilities of actors in a complex system makes things LESS complicated. It just requires more work.
 
  • #17
AlephZero
Science Advisor
Homework Helper
6,994
291
We don't know what size or complexity Borek's application is, but in any sort of engineering, a "one size fits all" approach to design and implementation won't always produce optimal results.

I find the idea that to tell your code there are 30 days in September, you first need to build a factory to create instances of MonthLookup objects, is faintly ridiculous - but whatever floats your boat.
 
  • #18
DavidSnider
Gold Member
488
131
We don't know what size or complexity Borek's application is, but in any sort of engineering, a "one size fits all" approach to design and implementation won't always produce optimal results.

I find the idea that to tell your code there are 30 days in September, you first need to build a factory to create instances of MonthLookup objects, is faintly ridiculous - but whatever floats your boat.
You didn't understand Borek's problem so it's not surprising that you find it ridiculous.

I don't fully understand it either -- it was just a suggestion and I was not suggesting there is a "one-true-method" of doing it.
 
  • #19
SixNein
Gold Member
42
16
As long as it doesn't interfere with the performance and readability of the code, I do my best to avoid them.
Outside of bare metal programming like in embedded systems, global variables should probably be avoided entirely, and at most they should only be read only. First off, one loses complete control of scope in global variables. So the dependencies on the global variable are unclear. What functions are reading and writing to these global variables? They can cause all kinds of grief in mutithreaded code. There is no access control or validation on global variables. The namespace is made larger by global variables (basically what the singleton pattern above tries to solve). And finally there can be issues with dynamic libraries.

And in terms of performance, the most likely bottleneck for the application is either going to be stuck in a loop somewhere or reads and writes to IO. Don't worry so much about optimizing code running in O(1). While the global will save a push and pop from the stack, it comes at the high price discussed above.

So far I tend to disagree. It is not possible to pass variables by reference or value, only "Java style", so to write simple function to swap ints you need to do crazy tricks. That's a lesson I would prefer to forget.
Java is always pass by value. The only tricky thing to remember is how references work in a by value system. When one declares an object in java, the variable is a pointer to an object. When the variable is passed to another function, it will pass the value of the pointer. The function creates a new pointer, and assigns the value, and it becomes your reference inside the function. In c++, one would pass the address to the pointer itself and not the value contained at the address.

[Address of memory location][value of memory location]
blah [0x01][100]

C++
dosomething(blah)
push 0x01 #onto the stack
call dosomething

Memory:
blah [0x01][100]

Java
dosomething(blah)
push 100 #onto the stack
call dosomething

memory:
blah [0x01][100]
newblah [0x02][100]

In the main object, passing the pointers? That means passing pointers to documents, that would only pass them further, they don't need the information, so it is not a "cleanly defined interface that communicates what the objects need".
If document was independent of the lower level classes, then you would be right. But the document class has a dependency on the information because the composite classes require the information. In other words, the dependency will look something like document->somechild->someoperation(). So instead of operating on the data in some member function, it's doing the operation in a member function of a composite object.



Global variable seems a reasonable approach, even if it goes against orthodox OOP thinking.
Avoiding global variables is a principle of software engineering. It's a matter of cost vs benefit analysis. The cost is quite high for the reasons stated above, and the benefit is making o(1) code just a little faster. In other words, its trading the farm for a piece of gum.
 
Last edited:

Related Threads on Coding in Java - replacement for a global variable

Replies
6
Views
2K
Replies
2
Views
6K
  • Last Post
Replies
4
Views
991
  • Last Post
Replies
7
Views
3K
  • Last Post
Replies
5
Views
3K
Replies
2
Views
1K
Replies
7
Views
3K
  • Last Post
Replies
9
Views
1K
Replies
11
Views
4K
Replies
3
Views
3K
Top