开发者

How to Increment a class Integer references value in java from another method

package myintergertest;

/**
 *
 * @author Engineering
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        //this one does not increment 
        Integer n = new Integer(0);
        System.out.println("n=" + n);
        Increment(n);
        System.out.println("n=" + n);
        Increment(n);
        System.out.println("n=" + n);
        Increment(n);
        System.out.println("n=" + n);
        Increment(n);

        //this one will increment
        MyIntegerObj myInt = new MyIntegerObj(1);
        Increment(myInt);
        System.out.println("myint = " + myInt.get());
        Increment(myInt);
        System.out.println("myint = " + myInt.get());
        Increment(myInt);
        System.out.println("myint = " + myInt.get());

    }

    public static void Increment(Integer n) {
        //NO.  this doesn't work because a new reference is being assigned
        //and references are passed by value in java
        n++;
    }

    public static void Increment(MyIntegerObj n) {
        //this works because we're still operating on the same object
        //no new reference was assigned to n here.
        n.plusplus();   //I didn't know how to implement a ++ operator...
    }
}

The result for all of those is n=0. Integer n is an object and therefore passed by reference, so why isn't the increment reflected back in the开发者_运维知识库 caller method (main)? I expected output to be n=0 n=1 n=2 etc...

UPDATE: Notice I updated the code example above. If I'm understanding correctly, Jon Skeet answered the question of why myInt would increment and why n does not. It is because n is getting a new reference assigned in the Increment method. But myInt does NOT get assigned a new reference since it's calling a member function.

Does that sound like I understand correctly lol ?


No, objects aren't passed by reference. References are passed by value - there's a big difference. Integer is an immutable type, therefore you can't change the value within the method.

Your n++; statement is effectively

n = Integer.valueOf(n.intValue() + 1);

So, that assigns a different value to the variable n in Increment - but as Java only has pass-by-value, that doesn't affect the value of n in the calling method.

EDIT: To answer your update: that's right. Presumably your "MyIntegerObj" type is mutable, and changes its internal state when you call plusplus(). Oh, and don't bother looking around for how to implement an operator - Java doesn't support user-defined operators.


You could use an AtomicInteger from java.util.concurrent.atomic. It has a 'incrementAndGet' method which is suitable for your showcase.


You are looking for something similar to C++'s reference or to C#' out parameter. Java (and many other languages) does not support this.

This type of behavior is typically achieved by changing the method from void to (in this case) int: public static int increment(int n) { return ++n; }

If the method is already returning something then you can create a new class that has two fields (can even be public): the original return value and the new value of n.

Alternatively, you can also wrap the integer inside a generic Cell class. You only need to write this Cell class once:

public class Cell<T> {
  public Cell(T t) { value = t; }
  public void set(T t) { value = t; }
  public T get() { return value; }
}

You can then use it in all situations where you want to a method to change a primitive:

public static void increment(Cell<Integer> n) {
  n.set(n.get()++);
}

Cell<Integer> n = new Cell<Integer>(0);
increment(n);
increment(n);
increment(n);
System.out.println(n.get()); // Output: 3


As Jon Skeet mentioned, all methods in Java are pass-by-value, not pass-by-reference. Since reference types are passed by value, what you have inside the function body is a copy of the reference - this copy and the original reference both point to the same value.

However, if you reassign the copy inside the function body, it will have no effect on the rest of your program as that copy will go out of scope when the function exits.

But consider that you don't really need pass-by-reference to do what you want to do. For instance, you don't need a method to increment an Integer - you can just increment it at the point in your code where it needs to be incremented.

For more complex types, like setting some property on an Object, the Object you are working with is likely mutable; in that case a copy of the reference works just fine, since the automatic dereference will get you to the original object whose setter you are calling.


Side note: In my humble opinion, writing n++ on an Integer object is extremely misleading. This relies on a feature of Java called "autoboxing" where it converts primitives to their corresponding boxing objects -- like int to Integer or boolean to Boolean -- automatically and without warning. Frankly I think it's a bad feature. Yes, sometimes it makes your life simpler by automatically doing a handy conversion for you, but it can also do conversions that you did not intend and do not realize are happening, with unintended side effects.

Anyway, there are two ways to accomplish what you are apparently trying to do:

One: Have the increment function return a new Integer with the updated value. Like:

   public Integer increment(Integer n)
    {
      Integer nPlus=Integer.valueOf(n.intValue()+1);
      return nPlus;
    }

then call it with:

Integer n=Integer.valueOf(0);
n=increment(n); // now n==1
n=increment(n); // now n==2

Etc.

Two: Create your own class that resembles Integer but that is mutable. Like:

class MutableInteger
{
  int value;
  public MutableInteger(int n)
  {
    value=n;
  }
  public void increment()
  {
    ++value;
  }
  ... whatever other functions you need ...
}

Of course the big catch to this is that you pretty much have to re-invent the Integer class.


You can't. Java is strictly pass-by-value.

See http://javadude.com/articles/passbyvalue.htm

Your choices are to wrap the integer in an object (or array), pass that in and update, return a value, or make the integer a class/instance variable.

Which is better depends on the situation.


As DerMike mentioned you can achieve this as follows:

public void doStuff() {
  AtomicInteger i = new AtomicInteger(0);
  increment(i);
  System.out.println(i);
 }

  public void increment(AtomicInteger i) {
    i.set(i.get() + 1);
 }


Integer is a value object which means that is value can't change.

Note that n++ is the equivalent of n = n + 1. You're just changing the value referred to by the local variable n, not the value of n itself.


See AtomicInteger: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html

You can do it thread-safe using this java.util.concurrent class.


public class passByReferenceExample {
    static void incrementIt(Long b[]){
        Long c = b[0];
        c=c+1;
        b[0]=c;

    }
    public static void main(String[] args) {
        Long a[]={1L};  

        System.out.println("Before calling IncrementIt() : " + a[0]);
        System.out.println();
        incrementIt(a);
        System.out.println("after first call to incrementIt() : " + a[0]);
        incrementIt(a);
        System.out.println("after second call to incrementIt(): "+ a[0]);
        incrementIt(a);
        System.out.println("after third call to incrementIt() : "+ a[0]);
        incrementIt(a);
        System.out.println("after fourth  call to incrementIt(): "+ a[0]);    
    }
}

output:

Before calling IncrementIt() : 1

after first call to incrementIt() : 2
after second call to incrementIt(): 3
after third call to incrementIt() : 4
after fourth  call to incrementIt(): 5
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜