Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 7 of 7

Thread: Why doesn't this change the variables that are passed in?

  1. #1
    Junior Member
    Join Date
    Jan 2014
    Location
    Minnesota
    Posts
    9
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Why doesn't this change the variables that are passed in?

    Hi, I'm having some trouble figuring out how to change the value of a variable that is passed into a class.
    I've tried just changing the variable, I've tried changing it by using the this.variable command, and I've even tried calling the setter class from within the class to change it, but it's still not working right. Any help would be appreciated.

    The first class is the one with Main in it and I just feed it some dummy data:

    public class ExamConverter {
     
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Age testAge = new Age();
     
    		testAge.setTestDay(4);
    		testAge.setTestMonth(5);
    		testAge.setTestYear(2014);
    		testAge.setClientDay(5);
    		testAge.setClientMonth(5);
    		testAge.setClientYear(1971);
     
    		System.out.println("Test: " + testAge.getTestMonth() + "/" + testAge.getTestDay() + "/" + testAge.getTestYear());
    		System.out.println("DOB: " + testAge.getClientMonth() + "/" + testAge.getClientDay() + "/" + testAge.getClientYear());
    		System.out.println("Age Years: " + testAge.AgeYears() + " Months: " + testAge.AgeMonths() + " Days: " + testAge.AgeDays());
     
     
     
    	}
     
    }

    This is the other class to calculate the age the way we do it on psych tests - it might not be mathematically accurate, but it's what all the tables and such for raw to scaled score conversion are based on, so the math needs to be the same as opposed to "accurate" because of some months having 30 or 31 days, etc.

    public class Age {
     
    	//==================Properties==================
    	// Variables for the test date and client date of birth
     
    	private int TestMonth;
    	private int TestDay;
    	private int TestYear;
    	private int ClientMonth;
    	private int ClientDay;
    	private int ClientYear;
     
    	//==================Constructor==================
     
    	public Age(){
     
    	}
     
     
    	//=================Property Methods================
    	// Used to change state of the class - getters and setters
     
    	public int getTestMonth() {
    		return TestMonth;
    	}
     
    	public void setTestMonth(int testMonth) {
    		TestMonth = testMonth;
    	}
     
    	public int getTestDay() {
    		return TestDay;
    	}
     
    	public void setTestDay(int testDay) {
    		TestDay = testDay;
    	}
     
    	public int getTestYear() {
    		return TestYear;
    	}
     
    	public void setTestYear(int testYear) {
    		TestYear = testYear;
    	}
     
    	public int getClientMonth() {
    		return ClientMonth;
    	}
     
    	public void setClientMonth(int clientMonth) {
    		ClientMonth = clientMonth;
    	}
     
    	public int getClientDay() {
    		return ClientDay;
    	}
     
    	public void setClientDay(int clientDay) {
    		ClientDay = clientDay;
    	}
     
    	public int getClientYear() {
    		return ClientYear;
    	}
     
    	public void setClientYear(int clientYear) {
    		ClientYear = clientYear;
    	}
     
    	//=================General Methods==================
    	// Calculate years, months, days old based on pen & paper
    	// methods.
     
    	public int AgeDays(){
    		int Days = 0;
     
    		if (ClientDay > TestDay){
    			this.TestMonth--;
    			this.TestDay = TestDay+30;
    		}else{
    			Days = TestDay - ClientDay;
    		}
     
    		return Days;
    	}
     
    	public int AgeMonths(){
    		int Months = 0;
     
    		if (ClientMonth > TestMonth){
    			this.TestYear--;
    			this.TestMonth = TestMonth+12;
    		}else{
    			Months = TestMonth - ClientMonth;
    		}
     
    		return Months;
    	}
     
    	public int AgeYears(){
    		int Years = 0;
     
    		Years = TestYear - ClientYear;
     
    		return Years;
    	}
     
    }

    Based on this dummy data, the output is:
    Test: 5/4/2014
    DOB: 5/5/1971
    Age Years: 43 Months: 0 Days: 0

    However, it should be:
    Test: 5/4/2014
    DOB: 5/5/1971
    Age Years: 42 Months: 11 Days: 29

    Thanks in advance!


  2. #2
    Junior Member
    Join Date
    Jan 2014
    Location
    Minnesota
    Posts
    9
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: Why doesn't this change the variables that are passed in?

    Well, I figured out part of the problem. I need to remove the "else" parts of the if...then...else code. That fixed the month and year calculations. However, I'm still not getting the year. The only thing I can think of is having a flag set to indicate that the year would change...

    Maybe there is a better way to program this...ideas?

  3. #3
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    SW Missouri
    Posts
    20,444
    Thanks
    49
    Thanked 2,218 Times in 2,191 Posts

    Default Re: Why doesn't this change the variables that are passed in?

    The posted code mixes usage of local variables and class instance variables making it very confusing on where the real values are that the methods are computing.
    If you don't understand my answer, don't ignore it, ask a question.

  4. #4
    Member
    Join Date
    Feb 2014
    Posts
    180
    Thanks
    0
    Thanked 48 Times in 45 Posts

    Default Re: Why doesn't this change the variables that are passed in?

    Try this:

    1. Remove the else statement in both the AgeDays and AgeMonths methods, but keep the body of the else blocks. (You mentioned you've done this already in post #2?)

    2. In ExamConverter, replace the final System.out.println statement with the following:
    System.out.println("Age Days: " + testAge.AgeDays() + " Months: " + testAge.AgeMonths() + " Years: " + testAge.AgeYears());

    Do you now get the right output? If you do, can you see why, and can you find a way to avoid problems like this? (Give this a thought. I'll later suggest a way to avoid such problems.)

    With regards to the mixed usage of local and instance variables, one way to make it obvious is to always add a "this." prefix when referring to instance variables. Another way is to adopt a convention in naming instance variables. In my previous workplace in the past the underscore prefix convention was used, e.g., _clientDays.

  5. #5
    Junior Member
    Join Date
    Jan 2014
    Location
    Minnesota
    Posts
    9
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: Why doesn't this change the variables that are passed in?

    Quote Originally Posted by jashburn View Post
    Try this:
    Do you now get the right output? If you do, can you see why, and can you find a way to avoid problems like this? (Give this a thought. I'll later suggest a way to avoid such problems.)

    With regards to the mixed usage of local and instance variables, one way to make it obvious is to always add a "this." prefix when referring to instance variables. Another way is to adopt a convention in naming instance variables. In my previous workplace in the past the underscore prefix convention was used, e.g., _clientDays.
    Hi Jashburn,
    I actually figured out the issue (I did use the "this." as I mentioned in the initial post, but it didn't make a difference since there weren't duplicate variables in the same class) but clearly it's a logic error in the code since if things are done "in order" it works fine. So I need to figure out a way so that it checks all of them regardless of which one is done first without doing a double subtraction on years and/or months. I've been playing with temp boolean variables trying to set up flags, but that isn't working well. I'm also looking at combining the AgeTimes into one method.

    I would welcome the feedback on fixing the logic so it works right.

  6. #6
    Member
    Join Date
    Feb 2014
    Posts
    180
    Thanks
    0
    Thanked 48 Times in 45 Posts

    Default Re: Why doesn't this change the variables that are passed in?

    With regards to "this.", I believe Norm was just commenting that without syntax highlighting, due to the naming of the instance and local variables it is not easy to tell them apart. (For me I don't really care because I plonked your code into my IDE with syntax highlighting, although I've noted your unconventional use of uppercase in method and variable names.)

    There are at least 2 ways to address this. The order in which the calculation is done is important.

    1. Combine AgeDays, AgeMonths and AgeYears methods

    As you suggested, 1 way to avoid the mistake is to combine the 3 methods into a single method. This way you have complete control over the order in which the calculation is done in the method body. You do need to think about how you would want to print out the results in ExamConverter though.

    2. Private-ise AgeDays, AgeMonths and AgeYears methods, provide a public calculation method, and use a data object for the result.

    There are 2 parts to this:

    a) Private-ise AgeDays, AgeMonths and AgeYears methods, provide a public calculation method

    The trouble at the moment is the 3 Age* methods are public, and so they are open to be called in any order. You can try using flags to control the side-effects of call-order, but it would not be easy to get them right. Instead, you can make these methods private, and provide a public calculateDiff method. calculateDiff can then call the Age* methods in the right order. This is very similar to #1, but instead of explicitly combining the code for the 3 methods, you're logically combining them through the use of calculateDiff.

    b) Use a (dumb) data object for the result

    Callers of calculateDiff are interested in 3 items: (age in) years, months and days. A method can return only 1 value/object. In order to be able to provide the 3 items, calculateDiff can create and return a data object that stores the items, and callers can extract them from the object.

    (Note: (b) can be used in conjunction with #1 above.)

    The following is a sample modification.

    public class Age {
     
        ...
     
        // =================General Methods==================
        // Calculate years, months, days old based on pen & paper
        // methods.
     
        // ### change to private
        private int AgeDays() {
            ...
            return Days;
        }
     
        // ### change to private
        private int AgeMonths() {
            ...
            return Months;
        }
     
        // ### change to private
        private int AgeYears() {
            ...
            return Years;
        }
     
        // ### add public method to perform calculation, taking care to call the methods in the right order.
        // ### returns an AgeResult data object.
        public AgeResult calculateDiff() {
            return new AgeResult(AgeDays(), AgeMonths(), AgeYears());
        }
     
        // ### add inner class to function as a data object
        public class AgeResult {
     
            private int years;
            private int months;
            private int days;
     
            // ### private constructor so only Age can instantiate this class.
            private AgeResult(int days, int months, int years) {
                this.days = days;
                this.months = months;
                this.years = years;
            }
     
            public int getYears() {
                return this.years;
            }
     
            public int getMonths() {
                return this.months;
            }
     
            public int getDays() {
                return this.days;
            }
        }
     
        // ### example usage
        public static void main(String[] args) {
            Age age = [... create and set up Age ...]
            AgeResult result = age.calculateDiff();
     
            System.out.printf("\nyears: %d\tmonths: %d\tdays: %d", result.getYears(),
                result.getMonths(), result.getDays());
     
        }
    }

  7. #7
    Junior Member
    Join Date
    Jan 2014
    Location
    Minnesota
    Posts
    9
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: Why doesn't this change the variables that are passed in?

    Thanks for the input Jashburn! That does make sense.

    I guess the context might help. Basically, I'm trying to write a program that will convert raw scores to scaled scores for a bunch of the psychological tests I use. They all convert ages based on the math I used in the class which is basically DOB subtracted from test date and if the DOB is smaller on the month or day field you deduct 1 from the "higher temporal order" column and add either 12 or 30 respectively.

    The information returned would probably need to be the int result from each of those since most tables divide up based on usually years and months, but some go out to day, so I would need to check all 3 to find the appropriate lookup table of information. For example, one test I'm looking at now, the Bender-Koppitz, divides things like 8 years, 0 months to 8 years 3 months, 8 years 4 months to 8 years 7 months, etc. Then you look up the raw score to get the scaled score and percentile rank. Once you have that score you can look up the age equivalent, etc etc...

    Sorry for the naming conventions. I was going by the lessons I was learning watching the AppDev Object Oriented Programming series.

Similar Threads

  1. Passed array value is null
    By NoobException in forum What's Wrong With My Code?
    Replies: 2
    Last Post: May 23rd, 2013, 10:01 PM
  2. Differences between local variables and instance variables
    By rob17 in forum Java Theory & Questions
    Replies: 2
    Last Post: March 6th, 2012, 07:34 PM
  3. Instance Variables and local variables difference
    By dcwang3 in forum Java Theory & Questions
    Replies: 3
    Last Post: October 31st, 2011, 06:33 AM
  4. [SOLVED] How to Put Spaces in the Output of Passed Arguments?
    By EmSaint in forum What's Wrong With My Code?
    Replies: 5
    Last Post: January 25th, 2010, 03:04 PM
  5. [SOLVED] loop , passed and failed
    By chronoz13 in forum Loops & Control Statements
    Replies: 5
    Last Post: August 25th, 2009, 07:00 AM