Uel.Rose
Uel.Rose

Reputation: 23

Value of a variable pass from method overwrite when method call again - Java

I'm a student and currently learning java. From what I know, java reads codes from top to bottom, but my programs behaviour is confusing me. This is not the my complete program, I created a simpler program to emphasize the part that I don't understand.

I had two projects:

Problem.java - my main project.

Procedures.java - contain many public void methods, I just create this to reuse a set of codes. Example: GetAllDigits() - this is to get every digits/char of a String and store inside an ArrayList.

As you can see after I pass variable account to GeAllDigits() I immediately parse the values to String AllDigits (this is to save the first result. I did this because I know I will call the method again and will have an another result).Then I store the second result inside variable ThreeDigits.

So my expected output should be:

All Digits: [2, 0, 1, 0, 0, 5]

Three Digits: [2, 0, 1]

But instead I get:

All Digits: [2, 0, 1]

Three Digits: [2, 0, 1]

String account = "201005";
ArrayList<String> AllDigits = new ArrayList<>();
ArrayList<String>  ThreeDigits = new  ArrayList<>();
String num = new String();

Public Problem()
{   int length = account.length();
    Procedures proc = new Procedures();
    proc.GetAllDigits(account);
    AllDigits = proc.digits;

    for(int x=0;x < (length-3);x++)
    {
        num += AllDigits.get(x);
    }
    proc.GetAllDigits(num);
    ThreeDigits = proc.digits;

    System.out.println("All Digits: " + AllDigits.toString());
    System.out.println("Three Digits: " + ThreeDigits.toString());
}

public static void main(String[] args) {
    new Problem();
}

This is what Procedures.java looks like:

public ArryList<String> digits = new ArrayList<>();

public void OddEvenDigits(String number)
{...
}

public void GetAllDigits(String acc){
    digits.clear();
    for(int i =0; i < acc.length(); i++)
     {
       int j = Character.digit(acc.charAt(i), 10);
       digits.add(Integer.toString(j));
     }
}

Sorry for my long post regarding such a simple problem. Any answer would be greatly appreciated, and if there are any sites/books that you can refer me to for learning that would be awesome!

Upvotes: 2

Views: 1192

Answers (5)

nbrooks
nbrooks

Reputation: 18233

There are a number of problems in your code. Often, the simplest way to tackle these is to reduce your code to simplest example you can think of, and get it working piece by piece until you are able to identify what's causing the issue.

Replace Use of Global Variable With Stateless Method

In this case, you're referring to the same global variable digits (in your proc instance) in multiple places, so when its value changes it changes everywhere.

The solution is to make Procedures.getAllDigits static, and stateless. Don't have it rely on a shared instance variable. It should create a new List each time, and return that value. This way, the logic for getAllDigits doesn't rely on anything outside of that method. See simple example below.

Naming Conventions

Additionally, you're flouting the Java naming conventions all over your code. Method names and variable names should be in lowerCamelCase. Class names should be in UpperCamelCase. Believe me when I say it makes a huge difference in readability, and therefore making your code easier to understand.

Other Things to Note

  1. When building up a String while looping, use a StringBuilder
  2. No need to move your logic from your main method to an object Constructor (e.g. new Problem()). Constructors should only be responsible for creating instances of an object, not housing the logic of your application.

import java.util.ArrayList;
import java.util.List;

public class Problem {

    public static void main(String[] args) {
        String account = "201005";

        List<String> allDigits = Procedures.getAllDigits(account);

        StringBuilder builder = new StringBuilder();

        for(int x = 0; x < account.length() - 3; x++) {
            builder.append(allDigits.get(x));
        }

        List<String> threeDigits = Procedures.getAllDigits(builder.toString());

        System.out.println("All Digits: " + allDigits.toString());
        System.out.println("Three Digits: " + threeDigits.toString());
    }

    private static class Procedures {
        private static List<String> getAllDigits(String acc) {
            List<String> digits = new ArrayList<>();

            for(int i =0; i < acc.length(); i++) {
                int j = Character.digit(acc.charAt(i), 10);
                digits.add(Integer.toString(j));
            }

            return digits;
        }
    }
}

Upvotes: 0

Vishy
Vishy

Reputation: 1362

It will be easier for you if you can learn Debugging in some IDE or print all values after they change in the program to understand behavior of the code you have written. To answer your question,

All Digits: [2, 0, 1]

This is happening because of this line where you are using length-3:

for(int x=0;x < (length-3);x++)

Validate it by writing another println like this:

Procedures proc = new Procedures();
proc.GetAllDigits(account); //Call1 GetAllDigits("201005")
AllDigits = proc.digits;

//This should print  [2, 0, 1, 0, 0, 5]
System.out.println("All Digits: " + AllDigits.toString());

// (length-3) reduces the string to be traced by 3
for(int x=0;x < **(length-3)**;x++)
{
    num += AllDigits.get(x);
}

//Value of num = "201"
proc.GetAllDigits(num); //Call2 GetAllDigits("201"). Here ArrayList digits gets cleared
ThreeDigits = proc.digits;

System.out.println("All Digits: " + AllDigits.toString());
System.out.println("Three Digits: " + ThreeDigits.toString());

Suggested changes in your code if you want to retain values:

public ArryList<String> GetAllDigits(String acc){
    public ArryList<String> digits = new ArrayList<>();
    //digits.clear();

    for(int i =0; i < acc.length(); i++)
     {
       int j = Character.digit(acc.charAt(i), 10);
       digits.add(Integer.toString(j));
     }

     return digits;
}

And try this in the Program():

Public Problem()
{   int length = account.length();
    Procedures proc = new Procedures();
    AllDigits = proc.GetAllDigits(account);
    //AllDigits = proc.digits;

    for(int x=0;x < (length-3);x++)
    {
        num += AllDigits.get(x);
    }
    ThreeDigits = proc.GetAllDigits(num);

    System.out.println("All Digits: " + AllDigits.toString());
    System.out.println("Three Digits: " + ThreeDigits.toString());
}

Recommend you to study following concepts to further your knowledge: - Debugging Code - static Functions - Naming conventions in Java. Hope this helps. Happy coding!

Upvotes: 0

Gaur93
Gaur93

Reputation: 695

You are getting
All Digits: [2, 0, 1] Three Digits: [2, 0, 1] because you call GetAllDigits from same proc object.
In java an object can have multiple references so each time you call GetAllDigits from same proc object this change is reflected in all references that's why Alldigits and Threedigits are same
To get the required values call GetAllDigitsfrom a new procobject.

Upvotes: 1

user6939075
user6939075

Reputation: 1

Try printing AllDigits.toString() before calling proc.getAllDigits(num). Inside Procedure, you have a member called digits which is an array list that gets cleared and set to new numbers every time you call getAllDigits(). So, when you print out AllDigits and ThreeDigits, they are both just printing out the values in proc.digits which most recently got updated to [2,0,1]

take a look at this post regarding duplicating values in java but talks about references to objects which will help you understand this issue.

Upvotes: 0

Anthony
Anthony

Reputation: 116

The problem occurred because you used the same instance of Procedures. When your code reached the line

proc.GetAllDigits(num);

it changed the value of proc.digits

which you used in setting the value of AllDigits and ThreeDigits.

Try to create a new instance of Procedures ie Procedures procs = new Procedures(); procs.GetAllDigits(num);

Upvotes: 0

Related Questions