Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Coding in Java - replacement for a global variable

  1. Feb 4, 2014 #1

    Borek

    User Avatar

    Staff: Mentor

    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?
     
  2. jcsd
  3. Feb 4, 2014 #2

    AlephZero

    User Avatar
    Science Advisor
    Homework Helper

    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 (Text):

    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 (Text):

    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: Feb 4, 2014
  4. Feb 5, 2014 #3

    Borek

    User Avatar

    Staff: Mentor

    Thanks, that's a solution I didn't thought of.

    Something to think about! Could be that's what I am missing.
     
  5. Feb 5, 2014 #4
    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).
     
  6. Feb 5, 2014 #5

    Borek

    User Avatar

    Staff: Mentor

    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: Feb 5, 2014
  7. Feb 5, 2014 #6

    AlephZero

    User Avatar
    Science Advisor
    Homework Helper

    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!
     
  8. Feb 5, 2014 #7

    DavidSnider

    User Avatar
    Gold Member

    The design pattern for this is called a 'singleton'.
     
  9. Feb 6, 2014 #8
    Indeed.

    Like this:

    Code (Text):
    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: Feb 6, 2014
  10. Feb 6, 2014 #9

    Borek

    User Avatar

    Staff: Mentor

    Yes, singleton is a great solution.

    In a way it classifies as hack :wink:
     
  11. Feb 6, 2014 #10
    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 (Text):
    package myProg;

    class GlobalStuff {
        int abc = 3;
    }
     
    MyProg.java
    Code (Text):

    package myProg;
    import static myProg.GlobalStuff.*;

    public class MyProg {
        public static void main(String[] args) {
            System.out.println(abc);
        }
    }
     
  12. Feb 7, 2014 #11

    SixNein

    User Avatar
    Gold Member

    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: Feb 7, 2014
  13. Feb 7, 2014 #12

    Borek

    User Avatar

    Staff: Mentor

    As long as it doesn't interfere with the performance and readability of the code, I do my best to avoid them.

    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.

    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.
     
  14. Feb 7, 2014 #13

    DavidSnider

    User Avatar
    Gold Member

    Also look up dependency injection. It's less hacky than singletons with the same effect.
     
  15. Feb 7, 2014 #14

    DavidSnider

    User Avatar
    Gold Member

    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: Feb 7, 2014
  16. Feb 7, 2014 #15

    AlephZero

    User Avatar
    Science Advisor
    Homework Helper

    I think Lewis Carroll would have loved OOP.
     
  17. Feb 7, 2014 #16

    DavidSnider

    User Avatar
    Gold Member

    Limiting scope and constraining the responsibilities of actors in a complex system makes things LESS complicated. It just requires more work.
     
  18. Feb 7, 2014 #17

    AlephZero

    User Avatar
    Science Advisor
    Homework Helper

    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.
     
  19. Feb 7, 2014 #18

    DavidSnider

    User Avatar
    Gold Member

    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.
     
  20. Feb 7, 2014 #19

    SixNein

    User Avatar
    Gold Member

    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.

    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]

    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.



    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: Feb 7, 2014
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Coding in Java - replacement for a global variable
  1. Global variables. (Replies: 7)

Loading...