4

this may be simple or fairly difficult...I have no idea either way. Here's my code:

package looping;

import java.util.Scanner;

public class PayrollMethods2 {

    public static void main(String[] args) {

        int hours = 0;
        double wr = 0;
        double pay;

        getData(hours, wr);

        pay = calculatePay(hours, wr);

        System.out.println(pay);
        // TODO Auto-generated method stub

    }


    public static void getData(Integer hours, Double wr)
    {
        Scanner kb = new Scanner(System.in);


        System.out.print("Please enter your wage rate ");
        wr = kb.nextDouble();

        System.out.print("Please enter your hours work ");
        hours = kb.nextInt();
    }



    public static double calculatePay(int hours, double wr)
    {
        if(hours <= 40)
            return hours * wr;
        else
            return (40 * wr) + ((hours - 40) * (1.5* wr));
    }

}

I want to return the method "getData()" so that when I enter hours and wr on the keyboard, it will return the total. However, it return a total of 0.0 no matter what I press. I know it has something to do with me assigning a value of 0 to the variables and also that the method is "void". But I have no idea how to modify the getData() method so that it returns the proper values.

Steve Kuo
  • 61,876
  • 75
  • 195
  • 257
  • 3
    For one, Java is pass by value. – Sotirios Delimanolis Feb 25 '14 at 20:58
  • Sorry new to JAVA, but I changed the main method to "getData(Interger, Double);"..I think that's what you meant but still nothing, but shouldn't there be a problem with the assigned variables initialized in main? – Circuuspeatnutz Feb 25 '14 at 21:09
  • @Circuuspeatnutz: It's a matter of scope and pass by value. You are assigning to the parameters. If you used an IDE like Netbeans, it would warn you of this. Since you aren't storing the values anywhere outside that method, they essentially get thrown away in `getData`. – Engineer2021 Feb 25 '14 at 21:10
  • Thanks for your help! I understand the pass value now lol. – Circuuspeatnutz Feb 25 '14 at 21:13
  • @SotiriosDelimanolis Pass by value has never stopped anyone from modifying objects inside of a function. The problem here is that `Integer` objects are immutable. – Rainbolt Feb 25 '14 at 21:26
  • @John In `getData()`, OP is reassigning references to the parameters `hours` and `wr` and assuming that those should change in the calling code in `main()` in the arguments pass to the method. This has everything to do with pass by value and nothing to do with immutability. – Sotirios Delimanolis Feb 25 '14 at 21:30

4 Answers4

3

The issue you are facing is because the variables hours & wr are being passed by value to getData() so getData function has its own copy of the variables hours & wr.

main :(initialize)

Variable    Value    Memory Address
hours         0       44444
wr            0.0     55555

getData : hours & wr are different than main so they have different address

Variable    Value    Memory Address
hours         0       66666
wr            0.0     77777

user enters values now : hours - 10 , wr - 20

Variable    Value    Memory Address
hours         10       66666
wr            20.0     77777

main : When control comes back to main the value of hours & wr is stil 0

Variable    Value    Memory Address
hours         0       44444
wr            0.0     55555

Solution :

This problem can be resolved by encapsulating the salary info into a object and then passing that object around( Objects are passed by Reference in Java) :

class Salary
{
  int hours;
  double wr;
}

Now in getData you can create an object of data Salary based on user input info and pass that Object to calculatePay

public static Salary getData()
{
    Scanner kb = new Scanner(System.in);
    Salary sal = new Salary();

    System.out.print("Please enter your wage rate ");
    sal.wr = kb.nextDouble();

    System.out.print("Please enter your hours work ");
    sal.hours = kb.nextInt();

    return sal;
}

public static double calculatePay(Salary sal)
{
}
Ingo
  • 36,037
  • 5
  • 53
  • 100
Kakarot
  • 4,252
  • 2
  • 16
  • 18
  • Thank u! I think I understand the variable error. Its because hours and wr had a defined value of "0' right? – Circuuspeatnutz Feb 25 '14 at 21:15
  • 1
    No its becuase you were passing those variables by value..so any modifications you make to them in getData will not be propogated – Kakarot Feb 25 '14 at 21:18
2

You need to either make wr and hours into static variables inside the class, or you need to have two getData methods and have them return, or you need to make a separate object to store wr and hours.

When you call a method variables are copied into the method. So when you change them inside the method it doesn't change anything outside the method. (If you pass an object in then a reference to the object is passed by value, so in that cases changes inside the object will be seen).

Tim B
  • 40,716
  • 16
  • 83
  • 128
2

Java is pass-by-value. It looks like you are trying to modify the parameters, which are locally scoped so you won't see the changes in main.

Java doesn't allow multiple returns, so you'll either have to create a class to pass back, or you can put the calls from the getData method into the main method.

Nicholas
  • 7,403
  • 10
  • 48
  • 76
-1

Normally, when you modify an object inside of a function, the changes are reflected outside of that function. Why do Integer objects behave differently? Take a look at the following code.

psv main (String[] args) {
    Integer i = new Integer(1);
    increment(i);
    System.out.println(i); // Prints 1!
}

void increment(Integer i) { i = i + 1; }

We expected a 2 to be printed, but a 1 is printed instead. This is because Integer is immutable.

Typically, if you pass an object into a function an modify its contents, you get a modified object. Because, when immutable objects are modified, a completely new object is created instead. If you create a completely new object, you are no longer modifying the old object!

Therefore, incrementing our Integer created an entirely new Integer that is local to the increment function.

Rainbolt
  • 3,542
  • 1
  • 20
  • 44
  • This doesn't have anything to do with immutability. If instead of `Integer`, you used some custom, mutable type, say `Custom`, and changed the reference, that change would not be reflected in the calling code. This is a consequence of Java being pass by value. See [here](http://stackoverflow.com/questions/40480/is-java-pass-by-reference). – Sotirios Delimanolis Feb 25 '14 at 21:39
  • @SotiriosDelimanolis If I created a custom object and tried to assign a primitive `int` to it, my program would probably crash. The magic lies in `Integer`'s custom `=` operator. Why does it require a custom assignment operator? Because it has no `setValue()` method. Why doesn't it have a `setValue()` method? Because it is immutable. – Rainbolt Feb 25 '14 at 21:48
  • You're misunderstanding. Given `public class Custom {}`, if you pass a `Custom` object that's bound to a method parameter `Custom c` and inside the method do `c = new Custom()`, that change will not be reflected in the calling code. This is what passing by value is all about. `Integer` is immutable, fine. But the root problem here is that reassigning references to parameter variables is not reflected in the arguments used to invoke the method. Java is pass by value. (It's hard to say all this in comments, would be easier in chat.) – Sotirios Delimanolis Feb 25 '14 at 21:51
  • @SotiriosDelimanolis The OP never once used the `new` operator, and neither did I, so you are comparing apples to oranges in your example. – Rainbolt Feb 25 '14 at 21:52
  • Again the `new` makes no difference, it's the `=`, reassigning references, that does. `hours = ...` – Sotirios Delimanolis Feb 25 '14 at 21:52
  • @SotiriosDelimanolis And why does assignment to an `Integer` create a new reference? – Rainbolt Feb 25 '14 at 21:53
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/48416/discussion-between-sotirios-delimanolis-and-john) – Sotirios Delimanolis Feb 25 '14 at 21:54
  • My issue is with this statement: `We expected a 2 to be printed, but a 1 is printed instead. This is because Integer is immutable.` It's not because `Integer` is immutable, it's because, even if you don't see it, there's a change of reference that occurs (and references are passed by value). The fact that `Integer` is used here doesn't matter. You could have had `Custom c` as a parameter and `c = someType.getCustom();` and OP would experience the same thing. – Sotirios Delimanolis Feb 25 '14 at 22:12