繁体   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...
    }
}

所有这些的结果是 n=0。 整数 n 是一个对象,因此通过引用传递,那么为什么增量没有反映在调用方方法(main)中? 我预计输出为 n=0 n=1 n=2 等等...

更新:注意我更新了上面的代码示例。 如果我理解正确,Jon Skeet 回答了为什么 myInt 会增加而 n 不会增加的问题。 这是因为 n 正在获取在 Increment 方法中分配的新引用。 但是 myInt 没有被分配一个新的引用,因为它正在调用一个成员函数。

这听起来像我理解正确吗哈哈?

不,对象不是通过引用传递的。 引用是按值传递的 - 有很大的不同。 Integer是不可变类型,因此您不能在方法中更改值。

你的n++; 声明是有效的

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

因此,它为Increment的变量n分配了一个不同的值 - 但由于 Java只有按值传递,这不会影响调用方法中n的值。

编辑:回答您的更新:没错。 大概您的“MyIntegerObj”类型是可变的,并且在您调用plusplus()时会更改其内部状态。 哦,不要费心四处寻找如何实现运算符 - Java 不支持用户定义的运算符。

您可以使用java.util.concurrent.atomicAtomicInteger 它有一个适合您展示的 'incrementAndGet' 方法。

您正在寻找类似于 C++ 的参考或 C# 的输出参数的内容。 Java(和许多其他语言)不支持这一点。

这种类型的行为通常是通过将方法从 void 更改为(在这种情况下)int 来实现的: public static int increment(int n) { return ++n; } public static int increment(int n) { return ++n; }

如果该方法已经返回某些内容,那么您可以创建一个具有两个字段(甚至可以是公共字段)的新类:原始返回值和 n 的新值。

或者,您也可以将整数包装在通用 Cell 类中。 你只需要编写一次这个 Cell 类:

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

然后,您可以在想要更改原语的方法的所有情况下使用它:

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

正如 Jon Skeet 所提到的,Java 中的所有方法都是按值传递,而不是按引用传递。 由于引用类型是按值传递的,因此函数体内的内容是引用的副本 - 此副本和原始引用都指向相同的值。

但是,如果您在函数体内重新分配副本,它将对程序的其余部分没有影响,因为该副本将在函数退出时超出范围。

但是考虑到您实际上并不需要通过引用来做您想做的事情。 例如,您不需要增加Integer的方法 - 您只需在代码中需要增加的点处增加它即可。

对于更复杂的类型,例如在对象上设置某些属性,您正在使用的对象可能是可变的; 在这种情况下,引用的副本就可以正常工作,因为自动取消引用将使您找到您正在调用其 setter 的原始对象。

旁注:以我的拙见,在 Integer 对象上编写 n++ 非常具有误导性。 这依赖于 Java 的一项称为“自动装箱”的功能,它将原语转换为相应的装箱对象——比如 int 到 Integer 或 boolean 到 Boolean——自动且没有警告。 坦率地说,我认为这是一个糟糕的功能。 是的,有时它会自动为您进行方便的转换,从而使您的生活变得更简单,但它也可以执行您不打算或没有意识到正在发生的转换,并产生意想不到的副作用。

无论如何,有两种方法可以完成您显然想要做的事情:

一:让增量函数返回一个带有更新值的新整数。 喜欢:

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

然后调用它:

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

等等。

二:创建自己的类,类似于 Integer 但它是可变的。 喜欢:

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

当然,最大的收获是您几乎必须重新发明 Integer 类。

你不能。 Java 是严格按值传递的。

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

您的选择是将整数包装在一个对象(或数组)中,传入并更新,返回一个值,或者使整数成为类/实例变量。

哪个更好取决于具体情况。

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

请注意, n++等效于n = n + 1 您只是在更改局部变量n引用的值,而不是n本身的值。

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

您可以使用这个 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]);    
    }
}

输出:

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