简体   繁体   English

如何从另一种方法增加java中的类整数引用值

[英]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.所有这些的结果是 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)?整数 n 是一个对象,因此通过引用传递,那么为什么增量没有反映在调用方方法(main)中? I expected output to be n=0 n=1 n=2 etc...我预计输出为 n=0 n=1 n=2 等等...

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.如果我理解正确,Jon Skeet 回答了为什么 myInt 会增加而 n 不会增加的问题。 It is because n is getting a new reference assigned in the Increment method.这是因为 n 正在获取在 Increment 方法中分配的新引用。 But myInt does NOT get assigned a new reference since it's calling a member function.但是 myInt 没有被分配一个新的引用,因为它正在调用一个成员函数。

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. Integer是不可变类型,因此您不能在方法中更改值。

Your n++;你的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.因此,它为Increment的变量n分配了一个不同的值 - 但由于 Java只有按值传递,这不会影响调用方法中n的值。

EDIT: To answer your update: that's right.编辑:回答您的更新:没错。 Presumably your "MyIntegerObj" type is mutable, and changes its internal state when you call plusplus() .大概您的“MyIntegerObj”类型是可变的,并且在您调用plusplus()时会更改其内部状态。 Oh, and don't bother looking around for how to implement an operator - Java doesn't support user-defined operators.哦,不要费心四处寻找如何实现运算符 - Java 不支持用户定义的运算符。

You could use an AtomicInteger from java.util.concurrent.atomic .您可以使用java.util.concurrent.atomicAtomicInteger It has a 'incrementAndGet' method which is suitable for your showcase.它有一个适合您展示的 'incrementAndGet' 方法。

You are looking for something similar to C++'s reference or to C#' out parameter.您正在寻找类似于 C++ 的参考或 C# 的输出参数的内容。 Java (and many other languages) does not support this. Java(和许多其他语言)不支持这一点。

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; }这种类型的行为通常是通过将方法从 void 更改为(在这种情况下)int 来实现的: public static int increment(int n) { return ++n; } 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.如果该方法已经返回某些内容,那么您可以创建一个具有两个字段(甚至可以是公共字段)的新类:原始返回值和 n 的新值。

Alternatively, you can also wrap the integer inside a generic Cell class.或者,您也可以将整数包装在通用 Cell 类中。 You only need to write this Cell class once:你只需要编写一次这个 Cell 类:

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.正如 Jon Skeet 所提到的,Java 中的所有方法都是按值传递,而不是按引用传递。 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.例如,您不需要增加Integer的方法 - 您只需在代码中需要增加的点处增加它即可。

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.在这种情况下,引用的副本就可以正常工作,因为自动取消引用将使您找到您正在调用其 setter 的原始对象。

Side note: In my humble opinion, writing n++ on an Integer object is extremely misleading.旁注:以我的拙见,在 Integer 对象上编写 n++ 非常具有误导性。 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.这依赖于 Java 的一项称为“自动装箱”的功能,它将原语转换为相应的装箱对象——比如 int 到 Integer 或 boolean 到 Boolean——自动且没有警告。 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.二:创建自己的类,类似于 Integer 但它是可变的。 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.当然,最大的收获是您几乎必须重新发明 Integer 类。

You can't.你不能。 Java is strictly pass-by-value. Java 是严格按值传递的。

See http://javadude.com/articles/passbyvalue.htmhttp://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:正如DerMike提到的,您可以按如下方式实现:

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. Integer是一个值对象,这意味着它的值不能改变。

Note that n++ is the equivalent of n = n + 1 .请注意, n++等效于n = n + 1 You're just changing the value referred to by the local variable n , not the value of n itself.您只是在更改局部变量n引用的值,而不是n本身的值。

See AtomicInteger: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html请参阅 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.您可以使用这个 java.util.concurrent 类来实现线程安全。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM