-2

So I've read about the pass-by-value nature of Java and I've tried to change my variable after passing it to a function by having the function return the variable again. I didn't succeed in that.

My code

public class Logic {
    private int position;

    public class Logic(){
        position = 1;
    }

    public void appendPosition(){
        position = calculatePosition(position);
    }
}

This is the barebones code. I call this method from an instance of Logic which is instantiated in another class:

public class MainLogic {
    ILogic L;

    public MainLogic(ILogic L){
        this.L = L;
    }

    public void start(){
        L.appendPosition();
    }
}

Through repeated debugging I find to my dismay that the position variable does not change at all. The position variable passed to calculatePosition changes fine, as expected. What am I missing? I've tried making the variable public and static.

calculatePosition

private int calculatePosition(int position){
        position += 6;
        if(snakeLocations[position]>0) {
            position -= 6;
        }
        else if(ladderLocations[position]>0) {
            position += 6;
        }
        return position;
    }

private final int[] snakeLocations = new int[] {0,0,0,0,0,0,0,0,0,9,0,0,0,13,0,0,0,0,0,19,0,0,0,0,0};
private final int[] ladderLocations = new int[] {0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,15,0,0,0,0,20,0,0,0,0};
KSHMR
  • 741
  • 1
  • 9
  • 24
  • And what is `calculatePosition(int)`? – Elliott Frisch Jan 31 '16 at 01:36
  • Could you post the `calculatePosition` method? – Calvin P. Jan 31 '16 at 01:36
  • I updated the OP with the method. For what it's worth I found that it does seem to change the position value. – KSHMR Jan 31 '16 at 01:38
  • Presumably `snakeLocations[7]` is `> 0` so you subtract `6` and the value doesn't change. – Elliott Frisch Jan 31 '16 at 01:38
  • Lightning fast reply! I'm pretty sure that that is not the case. I updated the OP with those values too. Positition starts at 1 always, and this happens at first try. – KSHMR Jan 31 '16 at 01:40
  • @Gudmundur Yes, but your first line adds 6. `+ 6` and `- 6` is `0`. – Elliott Frisch Jan 31 '16 at 01:44
  • Try creating a local variable to catch the value of position and use that instead. i.e. `calculatePosition(int position)` then `int p = position;` and use `p` instead of position throughout the method – Calvin P. Jan 31 '16 at 01:45
  • The if condition is false on first try I'm pretty sure, so it doesn't reach that -6 on first try. It stays at 7. – KSHMR Jan 31 '16 at 01:45
  • Note that it's poor form to have a local variable and an instance variable with the same name. – Hot Licks Jan 31 '16 at 01:47
  • @CalvinP. This is interesting. The new variable, p, doesn't show up in the debugger. Does that mean anything? – KSHMR Jan 31 '16 at 01:49
  • @CalvinP. - No, he should change the name of `position` in the prototype parm list for `calculatePosition` and not reference `position` *at all* inside that method. I don't believe that this is causing the problem, but it makes it hard to think about and debug. – Hot Licks Jan 31 '16 at 01:50
  • It means you're not looking in the right place in the debugger. – Hot Licks Jan 31 '16 at 01:51
  • @HotLicks I swear to god when I hover over the variable it says "not defined in current context" even though the breakpoint is after its declaration – KSHMR Jan 31 '16 at 01:52
  • It's not "defined" until a value is assigned to it. (Change it to be the method parm rather than a local variable.) – Hot Licks Jan 31 '16 at 02:03
  • Your classname is Logic, but you instantiate ILogic. So the last code is from some SampleLogic which implements ILogic? – user unknown Jan 31 '16 at 03:44
  • Your public class logic contains something which reminds me of a constructor, but with the keyword 'class' inside - it will not compile. You should test your simplified test code, before posting it, – user unknown Jan 31 '16 at 03:57

3 Answers3

0
public class Logic {
private int position;

public Logic(){
    position = 1;
}
//to get position.....................

public int getPosition(){
    return this.position;
}
public void appendPosition(){
    position = calculatePosition(position);
}
private int calculatePosition(int position){
    position += 6;
    if(snakeLocations[position]>0) {
        position -= 6;
    }
    else if(ladderLocations[position]>0) {
        position += 6;
    }
    return position;
}

private final int[] snakeLocations = 
        new int[] {0,0,0,0,0,0,0,0,0,9,0,0,0,13,0,0,0,0,0,19,0,0,0,0,0};
private final int[] ladderLocations = 
        new int[] {0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,15,0,0,0,0,20,0,0,0,0};
}

//next class

public class MainLogic {

Logic L;

public MainLogic(Logic L){
    this.L = L;
}

public void start(){
    L.appendPosition();
}

public static void main(String[] args) {
    Logic L = new Logic();
    MainLogic ml = new MainLogic(L);
    System.out.println(ml.L.getPosition());
    ml.start();
    System.out.println(ml.L.getPosition());
}

}
小土儿
  • 11
  • 4
-1

Let's read your code.

// There is a logic class.
public class Logic { 

    // So Logic has a position. it starts with zero.    
    private int position;

    // Logic also has an inner class, also called Logic.
    public class Logic(){
        position = 1;
        // When a new Logic().Logic() is created, the instance
        // variable of the parent instance gets set to one. WHAT?!?
    }
    // ... lots of code
}

So, It's a bit like that Yo Dawg! meme - I heard you like Logic, so we've put A logic instance into your Logic instance so you can Logic while your Logic.

You probably want a constructor.

// So this is Logic.
public class Logic {

    private int position;

    // When an Logic instance is created, position starts with 1.
    public Logic(){
        this.position = 1;
    }

Ok. So we're not talking about Yo Dawg Memes. So Let's talk pass by value.

Pass-by-value means classes are like very egotistic children: You can't play with their toys, unless they tell you so.

This is a good thing® since this means only the owning instance is allowed to change their private state. Trust me, it prevents quite a bit of havoc.

One way to allow the outside world to actually change the state is by using query and mutator methods. Back in the day, we used to call them getter and setter, but that sounds too simple, so software architects will usually use the fancier term.

But... all of this doesn't really apply since calculatePosition() is defined at Logic. Oops.

Let's try this:

  1. Renaming some instance variables
  2. Be a bit verbose to help the debugger. baby steps.

(Also, dropping a few jokes to fish for upvotes).

public class Logic {

    private int position = 1;

    public void appendPosition(){
        // When debugging strange stuff, 
        // keep each step simple. 
        // Is calculatePosition working as it should?
        int newPosition = calculatePosition(this.position);
        this.position = newPosition;
    }

    // Always use parameters as final. It's good karma.
    // You don't NEED to declare them as final,
    // but let's try to be EXTRA clear.
    private int calculatePosition(final int targetPosition){

        // Yes, make as much as you can immutable
        // You'll save a ton of mental bandwidth.
        final int localCopy = targetPosition +6;

        if(snakeLocations[localCopy]>0) {
            return (localCopy -6);
            // Don't force the maintenance programmer to 
            // read all your stuff. Return often, return early. 
            // This isn't Cc++, where you need to 
            // actually free your reference/pointers, 
            // so there's no point enforcing a single return.
        }
        if(ladderLocations[localCopy]>0) {
            return (localCopy+6);
        }
        return localCopy;
    }
}

So... Did this worked as it should?

Luiz Tavares
  • 482
  • 2
  • 11
-2

I found the answer. This is often my mistake in posting here. I try to strip down my code as much as possible to ease the work for you guys, but sometimes the problem lies outside of the scope of what I provide due to a lack of understanding, or oversight, on my part.

I was actually calling MainLogic from two levels above:

public mainFrame() {
        initComponents();
        logic = Factory.getMainLogic();
    }

where

public static class Factory {
    public MainLogic getMainLogic(){
        PlayerLogic pL = new PlayerLogic();
        ImageLogic iL = new ImageLogic();
        DieLogic dL = new DieLogic();
        MainLogic mainLogic = new MainLogic(pL,iL,dL);

        return mainLogic;
    }
}

I forgot I had accidentally put Factory as static. My sincerest apologies for wasting your time.

KSHMR
  • 741
  • 1
  • 9
  • 24