• Welcome to Valhalla Legends Archive.
 

[Java] Bypassing the default passing by value of primitive data types.

Started by Sorc.Polgara, November 18, 2005, 12:20 PM

Previous topic - Next topic

Sorc.Polgara

Ok, primitive data types such as int, double, boolean, etc. can only be passed-by-value to methods, and non-primitive data types such as classes and objects can only be passed-by-reference to methods.

I'm looking to find a way to pass-by-reference an integer.

Now, I know that asking for help with a problem on these forums without having shown that you have attempted or even thought about solving it yourself first is frowned upon.

Therefore, I'm going to tell/give the only solution to the problem that I have come up with so far.

Solution:
Use a single element integer array to pass an integer by reference.


NOTE:
I haven't tried searching the web yet.  I always try to do that as a last resort.  I like to ask the members on the vL Forums because most of the time the serious members are very helpful.

So, is there a better way to pass-by-reference primitive types such as an integer in Java?

Thanks.

Joe[x86]

If classes and objects are passed ByRef, take advantage of that.

public class ByRef_Integer {
  protected int value = 0;

  public ByRef_Integer(int i) {
    value = i;
  }

  public void setVal(int i) {
    value = i;
  }

  public int getVal() {
    return val;
  }
}


Very ugly, and untested, but the basic idea is down, and I'm rather sure it'll work.

EDIT -
Removed an "only" from the first sentence because it annoyed me.

EDIT -
Hm, I might as well explain this, because I'm bored. Create a new ByRef_Integer on the int you want to pass ByRef, pass that ByRef_Integer, and then when its returned, assign your int to getVal() of the ByRef_Integer.

Someone might want to make this Extending int? I haven't worked with Extending stuff, especially primitive data-types.
Quote from: brew on April 25, 2007, 07:33 PM
that made me feel like a total idiot. this entire thing was useless.

dxoigmn


Joe[x86]

You're only pretty sure, yet you provide a link? =p.

Yeah, that works too.
Quote from: brew on April 25, 2007, 07:33 PM
that made me feel like a total idiot. this entire thing was useless.

Sorc.Polgara

Uh oh... this code I wrote using the Integer class doesn't seem to be passing by reference.


public class PassByRef2
{
public static void passIntByRef(Integer n)
{
n *= 3;
}

  public static void main(String[] args)
{
Integer n = new Integer(5);

System.out.println("Before method call: " + n);

passIntByRef(n);

System.out.println("After method call: " + n);
}
}


The output is:
Quote
Before method call: 5
After method call: 5

Something is wrong.

Sorc.Polgara

I'm starting to think that the Integer class that comes with Java can't be passed by reference?

Here is a program out of my Java textbook that demonstrates passing by reference using the Point class/object

// Parameter passing demonstration
import java.awt.*;

public class PassingReferences {
// f(): set the value of the formal parameter
public static void f(Point v) {
v = new Point(0, 0);
}

// g(): modifies the contents of the referred to object
public static void g(Point v) {
v.setLocation(0, 0);
}

// main(): application entry point
public static void main(String[] args) {
Point p = new Point(10, 10);
System.out.println(p);

f(p);
System.out.println(p);

g(p);
System.out.println(p);
}
}


The output for this code is:
Quote
java.awt.Point[x=10,y=10]
java.awt.Point[x=10,y=10]
java.awt.Point[x=0,y=0]

Now what I did was just simply modify this code to see if the Integer class can be passed by reference.  Here is the code:

// Parameter passing demonstration
import java.lang.Integer;

public class PassingReferences {
// f(): set the value of the formal parameter
public static void f(Integer v) {
v = new Integer(0);
}

// g(): modifies the contents of the referred to object
public static void g(Integer v) {
v += 5;
}

// main(): application entry point
public static void main(String[] args) {
Integer p = new Integer(10);
System.out.println(p);

f(p);
System.out.println(p);

g(p);
System.out.println(p);
}
}


The output for the code is:
Quote
10
10
10

Very odd.

The Integer class included with Java doesn't seem to have a mutator method.  Maybe that is why?

Ender

You have a very common misconception, and it's good that you asked. NOTHING is passed by reference. EVERYTHING is passed by value. When you pass a data type (whether it be primitive or object) it's always passed as a value. In the case of objects, YOU then create your own reference to it.

So you see, when you pass objects you pass their values. Their values consist of (hopefully) an ecapsulated shell of data and methods. I'm not sure exactly why you want to pass an integer value in an object instead of a primitive, but the advantage of passing it in an object is that an object can hold an unfixed (well, relatively) amount of data and methods, where a primitive has a fixed amount of data capacity and holds a single data value within the range of its capacity. So if you want to pass an integer to a method and have this method transform the int value to a byte, you would use an Integer object, since the Integer object has methods that can do this for you.

And you should also know that an Integer is not an int. An integer doesn't have a single value, so you can't say Integer * 3. The Integer object does have an int value as a field (among other fields), which can be obtained by using a getter method on it.

Sorc.Polgara

Ok, my Professor gave me a problem to do, which is to basically find a way to pass by reference a integer.

So far I have one way of doing it and that is by using a single element integer array.  However, on Monday when I turn in my problem I want give more than one way of doing it.  Even if the other solution(s) are not the best and/or most practical.


NOTE:  Noone else in the CMSC-204 (Introduction to Computer Science) class was given this problem, only I was because skill-wise I have more programming experience than the rest of the students in the class.  I'm really suppose to be in CMSC-206 because I recieved a 3 on the AP Java exam.  If you have a 3 or above you are exempt from taking CMSC-204, however I confused the requirements for AP credit with another college when I registered for classes and I didn't realize that I could have skipped CMSC-204 until around the middle of the semester.  The only reason I didn't drop out of CMSC-204 when I realized this is because I decided to just stay in it and get an easy A to help get a good starting GPA for my college career (I'm a freshman).

----------------------------------------------------
Quote from: Ender on November 18, 2005, 02:52 PM
And you should also know that an Integer is not an int. An integer doesn't have a single value, so you can't say Integer * 3. The Integer object does have an int value as a field (among other fields), which can be obtained by using a getter method on it.

When I add a System.out.println() to see what the value of v is in the g() method it looks like it works.

// Parameter passing demonstration
import java.lang.Integer;

public class PassingReferences {
// f(): set the value of the formal parameter
public static void f(Integer v) {
v = new Integer(0);
}

// g(): modifies the contents of the referred to object
public static void g(Integer v) {
v *= 3;
System.out.println(v);
}

// main(): application entry point
public static void main(String[] args) {
Integer p = new Integer(10);
System.out.println(p);

f(p);
System.out.println(p);

g(p);
System.out.println(p);
}
}


The output for the code is:
Quote
10
10
30
10

The-FooL

I am really confused as to why you are multiplying a class by a primative.

Quote from: Sorc.Polgara on November 18, 2005, 03:08 PM

public static void g(Integer v) {
v *= 3;
System.out.println(v);
}


You need to use something like the wrapper class Integer, except one that has a .setInt type function (like joe said).  When the g method is called, it is passed a reference to the object.  You then need to modify this object within memory.  Also, you cannot just create a new Integer, as this will not overwrite the link in the calling function.

Ender

Quote from: The-FooL on November 18, 2005, 03:45 PM
I am really confused as to why you are multiplying a class by a primative.

Quote from: Sorc.Polgara on November 18, 2005, 03:08 PM

public static void g(Integer v) {
v *= 3;
System.out.println(v);
}


Quote from: Ender on November 18, 2005, 02:52 PM
And you should also know that an Integer is not an int. An integer doesn't have a single value, so you can't say Integer * 3. The Integer object does have an int value as a field (among other fields), which can be obtained by using a getter method on it.

Hm, fun to quote yourself :P You can't do Object * 3! Your multiplying an object by a number. What if a object has several int fields? How would it know what to multiply? This is why mathematical/logical/bitwise operators are done on primitives, not objects.  You also can't print out an Integer. For the same reason that you can't multiply an object by a number. You can only print out an int. So you have to do System.out.println(IntegerObject.intValue());    intValue() being the getter that returns the int field that you gave the Integer.

Quote from: Sorc.Polgara on November 18, 2005, 03:08 PM
The Integer class included with Java doesn't seem to have a mutator method.  Maybe that is why?

Of course it has mutator methods. What's the point of having data if you can't change it? I use the name setters/getters instead of mutators/accessors, because I hate it when people put big names to things and make it sound more complicated than it really is. I swear that people can get intimidated by the name of the subject before they even learn the content. Like stoichiometry in chemistry. Should be called "mass-math". Ok, but enough for advocating my opinions. You can see the interface for the Integer object by looking at the APIs at java.sun.com or by scrolling up to the link that dxoigmn posted. Or you could make your own Integer object. For your purposes, you may as well make your own. If you were doing stuff with the data that requires algorithms, like hashing and conversions, then you may as well use Sun's Integer class.

Quote from: Sorc.Polgara on November 18, 2005, 03:08 PM
Ok, my Professor gave me a problem to do, which is to basically find a way to pass by reference a integer.

Your teacher is wrong, you don't pass references to methods. You pass values. References point to the object's information and thus allow you to manipulate it. The object value contains the data. You can have several references that refer to the same object and manipulate the object in a way that other references understand this manipulation. Think of how linked lists work, like how head and tail both reference the same thing when it's empty, without ever referencing eachother. This drove me mad a few months ago ;P I was like, "wtf, does the transitive property apply to references!" It only really works for references, because references don't contain data, they point to data. If you have int a = 1,  b = 1; and then do int b = 2;        int a doesn't become 2. Because primitives don't reference objects.

In the case of objects, you create references for the arguments (values) that a method takes in. The parameters of a method define a local reference. 

I believe that your teacher simply wants you to use objects that have primitive data types as fields. You can give an Integer object it's integer value, and it sets this to an int field. Then you can request this field when you want it. Why create an Integer object instead of an int? Objects can have methods and data, primitives can only have a single data value. People sometimes refer to Objects such as the Integer object because it wraps an int value. Wrapper classes basically wrap a primitive data type and allow one to manipulate it easily.

If your teacher doesn't believe that he's wrong (not that I'm saying you should tell him that...), show him this.

Ender

Quote from: Joe on November 18, 2005, 12:24 PM
Someone might want to make this Extending int? I haven't worked with Extending stuff, especially primitive data-types.

Extending primitive data types? Are you referring to "extend" as in inheritance? In that sense, you can only extend classes. But if you are using the word "extend" in a different sense, what do you mean by it?

dxoigmn

Quote from: Joe on November 18, 2005, 01:20 PM
You're only pretty sure, yet you provide a link? =p.

Yeah, that works too.

I decided not to be lazy and provide a link. But using the Integer won't work since you need a setValue() method nor can you extend the class because it is final :\

The-FooL

Ender, I only quoted what he wrote to point out the mistake.  I wasn't saying it was right to multiply a class by a primative.

Ender


Sorc.Polgara

@Enders, Joe, etc.

Thanks for the help!

~~~~~~~~~~~~~~~~~~~~~~~~

Ok, today in class the teacher asked if "Mr. Hotshot" had found a solution the challenge and I gave him 2 different solutions.

1.  Use a single-element integer array.
2.  Create your own integer wrapper class.

NOTE:  I told him that it might be possible to use the built-in Integer class included with Java as a wrapper, but I had been unsuccessful in doing it.

The solution he was really looking for was #2, because later in the class he passed out some code on how solution #2 could be implemented.  Also, he hasn't gone over arrays yet in class, so he didn't want to confuse the already confused students.  He is not a very good teacher in my opinion.

Funny, the teacher was surprised.  Most, if not all of the students in the class know that I shouldn't be in there.  I spend almost 5 hours a week helping various students in the class with the homework... The math majors especially.