1
public class Apple
{
    private boolean isJuicy;
    private boolean isRipe;

    public Apple(boolean isJuicy)
    {
        isJuicy = isJuicy;
    }

    public void setRipe(boolean ripe)
    {
        this.isRipe = ripe;
    }

    public boolean isRipe()
    {
        return this.isRipe;
    }

}

In Spring I have two service classes AppleService & FruitService.

AppleService

public Apple createApple(boolean isJuicy)
{
    Apple apple = null;
    apple = new Apple(isJuicy);
    fruitService.saveApple(apple);

    log("ripe:" + apple.isRipe()); // false

    return apple;
}

FruitService

public void saveApple(Apple apple)
{
    if(apple.isJuicy())
        apple.setRipe(true);

    persist(apple);

    log("ripe:" + apple.isRipe()); // true

}

Why is the Apple reported as being ripe in the FruitService but not in the AppleService?

I thought the fact that it is passed by reference to the FruitService guarantees that the same object and object properties should be present in the apple object in the AppleService?

DataNucleus
  • 15,497
  • 3
  • 32
  • 37
Dmitriy
  • 11
  • 2
  • 3
    Let's start with the fact that Java *doesn't* use pass-by-reference. It uses pass-by-value for *everything*, but those values are either primitives or references. I don't think it's relevant to this problem, but it's worth being precise with terminology. – Jon Skeet Aug 07 '11 at 17:19
  • 2
    I find it hard to see how the behaviour you've reported is possible - or how Spring is involved, unless you're using some sort of interceptor which is cloning the input. I suggest you edit your code until you've got a short but *complete* example demonstrating the problem. I suspect that in coming up with such an example, you'll work out where the problem is. In particular, I would start by removing the persistence part. – Jon Skeet Aug 07 '11 at 17:21
  • You set it to ripe in fruit service. You never set it in apple service you only set isjuicy. Nothing to do with spring. – Kevin Aug 07 '11 at 17:27
  • @Kevin: But the point is that when AppleService calls FruitService, the change made in FruitService should still be visible back in AppleService - it's the same object. – Jon Skeet Aug 07 '11 at 17:30
  • Yes just noticed that, sorry! – Kevin Aug 07 '11 at 17:32

2 Answers2

1

Though I agree with the comments on the question (you need to post more code), I'm sure the core issue here is that, well, Java is never pass-by-reference. It passes primitive values for primitive values, and it passes "object references" (which are basically pointers) for objects.

In Java, when you get an object passed as a parameter, calling methods on the object will affect the original object passed. But actually assigning a value to the object will not affect the object passed, instead you'll set the reference (aka pointer) to a new object.

This is better explained here. You may also want to look at this StackOverflow question.

Community
  • 1
  • 1
Alexis King
  • 43,109
  • 15
  • 131
  • 205
1

I think the problem is this: you aren't setting isRipe to true in the constructor when isJuicy is passed in as true. In java, the default value for an unset boolean is false. This will fix it:

private boolean isRipe;

public Apple(boolean isJuicy) {
    this.isJuicy = isJuicy; // Note: added "this.", otherwise your assignment just sets the parameter to itself
    isRipe = isJuicy; // Set isRipe too
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722