0

I am having a rough time getting some of my code to work. The code starts a SwingWorker and gets the results. I am having trouble passing data to the worker and getting information back from the worker.

The data I want to pass is made up of objects of classes I defined myself. For example I have both an Item and Inventory object. The Item object contains basically all primitive types (name, price, etc) and the Inventory contains a LinkedList of Items.

I can't quite remember the series of events that lead up to my sanity check, but as a sanity check I implemented Item.getDeepCopy(Item inItem) and Inventory.getDeepCopy(Inventory) functions so that I could pass copies of Items and Inventorys to my workers. Is this needed?

How I use the deep copy functions is when I pass data to and get data from my StringWorkers. Say I launch a worker as a result of a button click. In the event handler I first get a deep copy of my classes private local copy of Inventory or Item and pass that to the workers constructor. Is this correct? Do I need to pass a deep copy? I think not..

I do this out of fear that the worker will try to modify the classes reference to the object within the worker itself causing some threading issues. But after some reading and critical thinking this couldn't be the case because java is pass-by-value, so what is passed to the worker cannot possibly lead to the GUI components data changing. Is this correct thinking?

Then when the worker is done, it calls an overridden done method I wrote. This method runs on the EDT so I can call functions from my GUI component, namely a function I call WorkerDone(boolean result, Inventory outInv). The worker calls this function and passes (not a deep copy) its local copy of Inventory or Item back to the GUI. When the GUI gets it it then performs a deep copy and sets its local Inventory or Item to this value. Is this a good use for the deep copy?

Edit: A little more.

Basically I want to pass "some data" to the worker and allow it to work on it with no link to the GUI components. When the worker is done it will either have finished successfully or not. If successful I want to get the data "back" from the worker and update my local copy with the data returned. I don't want the worker to "touch" any of the data in the GUI.

For mutable-ness. I want to be able to change the data within the object after it is created. This is how I build my application with this in mind. What I want is not non-mutable objects to keep things thread safe, I just don't want threads interacting. I want to pass the worker some data and basically "forget that I sent it" and then when the worker is done and it calls the GUI's workerDone method the GUI simply just agrees to set its local copy of the data to the value of the returned object if the worker says it was successful.

Edit 2:

Just for clearer understand of the phrases pass-by-value and pass-by-reference. What I think when I see pass-by-value. Say I want to pass an apple by value, to do this I would put my apple in a cloning machine that makes an exact clone of the apple same in every respect and pass that apple. Whomever is passed this cloned apple can do anything with it, and none of it affects my initial apple.

What I think of when I see pass-by-reference is that if I want to pass my apply by reference I write down where my apple is on a piece of paper and then pass that. Whomever receives this piece of paper can then come to where my apple is and take a bite of it.

So my confusion comes from "Java is pass-by-value", if it is, then why do I have to worry about my worker causing thread violations when operating on the value passed to it?

KDecker
  • 6,928
  • 8
  • 40
  • 81
  • 1
    Since you don't state the specific details of your requirement, it is uncertain if this is a good example or not. If you want to update the state of your `Item`s and `Inventory`s in background and these changes should be visible to user until the background work finish, then just pass your current objects. If you want to update the state but the user should still see the values before the update, then is a good example of deep clone. – Luiggi Mendoza Sep 08 '14 at 17:32
  • The point of the SwingWorker is to ensure safe modification of the GUI. You seem to be concerned with elements that are not necessarily GUI related(not shown directly on the screen), or? – ControlAltDel Sep 08 '14 at 17:34
  • I made an edit to try and make the details of the interaction clearer, if you could review and respond it would be more helpful to me! – KDecker Sep 08 '14 at 17:50
  • Hi - Your analogy is a good one. In this case, "pass by value" means 1) You have an apple, 2) the JVM gave you a piece of paper where the apple is (a "reference"), 3) when you pass the apple, you *pass a copy of that piece of paper*. Q: Does that help? – FoggyDay Sep 08 '14 at 18:41
  • Is there a way in java to de-reference the pointer and pass the data at the end of it to a function? Or is that why I wrote a deep copy? – KDecker Sep 08 '14 at 21:11

3 Answers3

3

Java is pass by value, but when you pass an object, you are passing a reference, and just a copy of that reference. Both references, the original and copy still refer to the same set of values in the heap.

It's valid to worry about code you have no control over possibly modifying your objects, but you could perhaps wrap that object in another that cannot be changed, or specify an interface that has the extract methods but not set methods.

Having the GUI have it's own copy of data could be useful if you might update the data, and halfway through updating the data you display it. If you have no worry about such inconsistencies, you may just want to share the same reference between the gui code and non-gui code to keep your code simple (assuming your classes here are thread-safe).

NESPowerGlove
  • 5,496
  • 17
  • 28
0

"Pass by value" means that an object reference is passed. A copy of the original reference, not a copy of the object's data.

In other words, all your callees see the same object (and can change it at will).

Here's a good article from the Oracle Java docs on strategies for making an object "immutable":

FoggyDay
  • 11,962
  • 4
  • 34
  • 48
  • *"Pass by value" means that the object reference is passed* what is passed is a copy of the value of the reference. – Luiggi Mendoza Sep 08 '14 at 17:38
  • But you state that you pass the object reference. This isn't how it works. – Luiggi Mendoza Sep 08 '14 at 17:40
  • This is basically the first half of my question. If I pass the worker a reference to my local object, does it copy ALL of the data in the object and then pass that to the function, or .. otherwise I am not sure what pass-by-value is.. – KDecker Sep 08 '14 at 17:40
  • Also, the solution to this problem is not making the class immutable. It depends on what you need. I have worked with mutable objects that are used through multiple threads. The thing is that I make sure that only a single thread can alter the state of this object. – Luiggi Mendoza Sep 08 '14 at 17:41
0

"Pass by value" and "pass by reference" describe how function arguments are passed on the stack. They have nothing to do with what can or can't happen to objects on the heap. Suppose that we write code in some completely made-up programming language:

def foo(x) :
    x = 5;
end

def bar() :
    a = 3;
    foo(a);
    print a;
end

What will the function bar() print? The answer depends on whether the parameter x in foo() is pass-by-value or pass-by-reference. In a pass-by-value language (e.g., in Java), the value of the local variable a is passed when bar() calls foo(a). The foo() function can modify its own copy of that value, but it can not modify the caller's local variable, a.

In a pass-by-reference language, the address of the caller's local variable is passed. The x in foo becomes an alias for the a in bar(), and the assignment, x=5 changes the value of the variable a in bar.

Java is always pass by value: A Java function can never, ever, modify its caller's local variables.

Where people get confused is, a Java value can either be a primitive type (int, double, char, ...), or it can be an object reference.

public javaFoo(MyType x) {
    x.setFrobber(true);
}

public javaBar() {
    MyType mt = new MyType();
    foo(mt);
    System.out.println(mt.toString());
}

The variable x in javaFoo() is a different variable from the variable mt in javaBar(), and "pass-by-value" means that the javaFoo() function can not change mt. BUT both variables refer to the same object, and javaFoo() can modify the object.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
  • That completely *made up* language resembles me to Ruby. – Luiggi Mendoza Sep 08 '14 at 19:40
  • 1
    Ok, (not in the sense of any language) x in `javaFoo` "points" to the location of the data `mt` also points to. `javaFoo` can modify the contents of the data at the location that `x` points to, but it cannot modify where `x` points? // Now I think I see where I went wrong. `MyType mt` is just a pointer to a location of the data, not the data itself. Pass-by-value means pass the value of the pointer, which is not the data in the object, but the data in the pointer to the object namely the memory location of the object. – KDecker Sep 08 '14 at 19:40
  • @BumSkeeter yes, you're correct. Just remember that Java doesn't directly let you work with the pointers or addresses like C/C++. – Luiggi Mendoza Sep 08 '14 at 19:43
  • @BumSkeeter basically your real problem is answered here: http://stackoverflow.com/q/40480/1065197 – Luiggi Mendoza Sep 08 '14 at 19:44
  • @LuiggiMendoza I read that post and all the answers multiple times... Not sure why it didn't click then. – KDecker Sep 08 '14 at 19:52
  • @LuiggiMendoza Did Matz not completely make up Ruby? – Solomon Slow Sep 08 '14 at 20:42