14

What is the best way to share data between separate classes in Java? I have a bunch of variables that are used by different classes in separate files in different ways. Let me try to illustrate a simplified version of my problem:

This was my code before:

public class Top_Level_Class(){
    int x, y;

    // gets user input which changes x, y;
    public void main(){
       int p, q, r, s;
       // compute p, q, r, s
       doA(p,q,r);
       doB(q,r,s);
    }

    public void doA(int p, int q, int r){
       // do something that requires x,y and p, q, r
    }

    public void doB(int q, int r, int s){
       // does something else that requires x, y and q, r, s
    }
}

Now it looks something like this:

public class Top_Level_Class(){
    int x, y;
    SomeClass1a a = new SomeClass1a();
    SomeClass1a b = new SomeClass1b();
    // gets user input which changes x, y;
    public void main(){
       int p, q, r, s;
       // compute p, q, r, s
       a.doA(p,q,r);
       b.doB(q,r,s);
    }

public class SomeClass1a() {  // in its own separate file
    public void doA(int p, int q, int r){
       // do something that requires x,y and p, q, r
    }
}


public class SomeClass1b() {  // in its own separate file
    public void doB(int q, int r, int s){
       // does something else that requires x, y and q, r, s
    }
}

So anyway, should I pass x and y each time (where x,y are variables stored in the helper class func) ?

 a.set(x,y);
 a.doA(p,q,r);

My idea was to have a special container class where x and y are held. The top level class would have an instance of the container class and change x,y using the set methods.

// in the top level class:
Container c = new Container(x,y);
a.setContainer(c);
b.setContainer(c);

My helper classes would also have an instance of the container and it would point to the same instance as in the top level. That way they access the same x,y as in the top level.

I would like to know if I should

  • Use the container class
  • Load x,y each time into the subclasses
  • ?? Some better method ??
f20k
  • 3,106
  • 3
  • 23
  • 32
  • 3
    The answer here is, sadly, 'it depends'. programmers.se might be a more fertile target for this question. – bmargulies Dec 12 '10 at 00:49
  • If the inner class is not static, then it can access parent class members as well... – Vojta Dec 12 '10 at 00:50
  • It's not an inner class if it's in a different file. And it's not a subclass if it doesn't extend the superclass. – Armand Dec 12 '10 at 03:25
  • Yes, subclass is was a poor choice of words on my part. I will edit this. – f20k Dec 12 '10 at 04:42

4 Answers4

20

I guess the answer to your question is the Design Pattern called Singleton. It basically allows you to get and exploits the same (and unique) instance of a class whenever you want in your system.

This is its implementation (please forgive possible syntax errors, I did not compile it):

class Container{

  //eventually provides setters and getters
  public float x;
  public float y;
  //------------

  private static Container instance = null;
  private void Container(){

  }
  public static Container getInstance(){
    if(instance==null){
       instance = new Container();
      }
      return instance;
  }
}

then if elsewhere in your code you import the Container you can write for example

Container.getInstance().x = 3;
temp = Container.getInstance().x;

and you will affect the attributes of the unique container instance you have in your system

In many cases it is however better to use the Dependency Injection pattern as it reduces the coupling between different components.

Andrea Sindico
  • 7,358
  • 6
  • 47
  • 84
  • Very interesting. It has a static variable of itself. Just wondering, how does this thing go out of scope? If it is static, won't it remain in existence? Or do I set it to null when I am done with it? – f20k Dec 14 '10 at 21:47
  • Sorry but I guess i have not understood your question :( anyway as its instance is static, once initialized, it will remain in existence. You do not have to, and you could not, set it to null. Consider it a shared repository of your variables :) However here is an explanation of the Pattern http://en.wikipedia.org/wiki/Singleton_pattern – Andrea Sindico Dec 14 '10 at 22:06
  • Hmm well the Singleton will make sense if I only need to instantiate it once. However, my top level function is actually a thread that will be instantiated/destroyed several times throughout the program execution. Well I suppose I can just overwrite the values each time. – f20k Dec 16 '10 at 18:23
  • creating and destroying the same thread many times during the execution of a system is quite strange. You might probably want to sleep it and awake it when needed – Andrea Sindico Dec 16 '10 at 20:07
  • I am writing a game for android. Given the framework, it is entirely possible for a user to play the game such that the thread is created and destroyed several times. The Android OS will destroy the thread as necessary to free up resources for other apps. Hmm. Maybe putting it to sleep may work, but I think android will still destroy it when the user leaves the game – f20k Dec 20 '10 at 15:40
  • I would like to add that you will find many people saying this pattern is pure evil because of the fact it is actually just a wrapper of a global variable. The problem is also that, in a singleton centric architecture, classes' dependencies may not be clear. I personally think that the Singleton pattern is just a Design Pattern helping you to be sure that class will only have one instance. It is not bad on itself it depends on how you use it. – Andrea Sindico Sep 28 '12 at 20:09
  • 1
    Use `instance != null` instead of `!instance`, because the `!` is not defined for this argument type. – Saeed May 11 '14 at 21:54
0

I am having a hard time seeing what your problem is -- why don't you want to pass x an y as a parameter?

Oh, well. Assuming you don't, I don't see a need for a new container class. Do it this way:

public class SubClass1a() {  // in its own separate file
    public void doA(Top_Level_Class caller, int p, int q, int r){
       // do something that requires x,y and p, q, r
       // **to get x use the expression term caller.getX() and caller.getY()**
    }
}

Of course you need to add the public getter methods getX() and getY() to Top_Level_Class.

If you do not want SubClass1a to be dependent on Top_Level_Class then you could create an interface that provides access to the variables.

AlanObject
  • 9,613
  • 19
  • 86
  • 142
  • Hmm okay. I'll have to take a look on interfaces more. The main reason I didn't want to pass x,y each time is because I have several functions in several SubClasses that each use (x,y, z, etc) and it didnt seem right to pass in like 6-8 variables each time I call a function. The sub classes used to be dependent, but I'm trying to take them out of the file so they can be used in a different project. – f20k Dec 12 '10 at 01:05
  • 1
    @f20k Your gut feeling about not wanting to pass 6-8 parameters to a method is on the right track. Parameter lists that are that long generally hint that you should consider bundling those parameters into an object or 2. – dhable Dec 12 '10 at 06:35
  • @Dan, thanks for your suggestion. I think I will implement a container. It makes a lot of sense. I was just worried that it would be bad programming practice if I shared the data this way. – f20k Dec 12 '10 at 16:35
0

Blockquote The main reason I didn't want to pass x,y each time is because I have several functions in several SubClasses that each use (x,y, z, etc) and it didnt seem right to pass in like 6-8 variables each time I call a function. The sub classes used to be dependent, but I'm trying to take them out of the file so they can be used in a different project. Blockquote

If this is the case then you are better off abstracting your variables out to a container class. If every instance of these no-longer-dependent classes is going to use a large subset of these variables then it makes sense to have them all in one instance. Variables that are logically related should be found in the same place. Your approach should be something like:

public class Top_Level_Class(){
Container container = new Container(x, y, p, q, r, s);
SubClass1a a = new SubClass1a(container);
SubClass1a b = new SubClass1b(container);
// gets user input which changes x, y using container's getters and setters
public void main(){
   // compute and set p, q, r, s
   a.doA();
   b.doB();
}

public class SubClass1a(Container c) {  // in its own separate file
    public void doA(c.getX, c.getY, c.getP, c.getQ, c.getR){
       // do something that requires x, y, p, q, and r
    }
}

public class SubClass1b(Container c) {  // in its own separate file

    public void doB(c.getX, c.getY, c.getQ, c.getR, c.getS){
       // does something else that requires x, y, q, r, and s
    }
}

public class Container(x, y, p, q, r, s) {
    //getters and setters for all variables
}

This keeps you from getting into a variable passing spaghetti-code situation, and when you want to use just one or two of these classes later your code is modular enough to port with just those classes and your container.

Raskolnikov
  • 286
  • 3
  • 13
0

This question is a bit mad - the code in the question won't compile.

public class Main {
    public static void main(String... args) {
        MutableDataContainer m = new MutableDataContainer();
        ImmutableDataContainer i = computeImmutableData();
        new ADoer().doA(m, i);
        new BDoer().doB(m, i);
    }
    ...
}

class MutableDataContainer {
    private int x, y;
    ... // getters and setters below
}

class ImmutableDataContainer {
    private final int p, q, r, s;
    ... // getters below
}

You'll need to define ADoer and BDoer as well.

Armand
  • 23,463
  • 20
  • 90
  • 119
  • Sorry, the code i wrote up there is to help give an idea of what I want to do. It doesnt actually work. The actual code is actually rather complicated with 100+ lines. I'm basically trying to share some very-often-used variables in the top_level_class between helper classes in separate files. The question is which method would be best - efficient-wise and oop-wise – f20k Dec 12 '10 at 04:50