Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何通过引用正确传递整数类?_Java_Integer_Pass By Reference - Fatal编程技术网

Java 如何通过引用正确传递整数类?

Java 如何通过引用正确传递整数类?,java,integer,pass-by-reference,Java,Integer,Pass By Reference,我希望有人能为我澄清这里发生了什么。我在integer类中搜索了一段时间,但是因为integer覆盖了+操作符,所以我无法找出哪里出了问题。我的问题是这一行: Integer i = 0; i = i + 1; // ← I think that this is somehow creating a new object! 我的理由如下: 我知道java是按值传递的(),所以我认为在下面的示例中,integer对象应该每次递增 public class PassByReference {

我希望有人能为我澄清这里发生了什么。我在integer类中搜索了一段时间,但是因为integer覆盖了
+
操作符,所以我无法找出哪里出了问题。我的问题是这一行:

Integer i = 0;
i = i + 1;  // ← I think that this is somehow creating a new object!
我的理由如下: 我知道java是按值传递的(),所以我认为在下面的示例中,integer对象应该每次递增

public class PassByReference {

    public static Integer inc(Integer i) {
        i = i+1;    // I think that this must be **sneakally** creating a new integer...  
        System.out.println("Inc: "+i);
        return i;
    }

    public static void main(String[] args) {
        Integer integer = new Integer(0);
        for (int i =0; i<10; i++){
            inc(integer);
            System.out.println("main: "+integer);
        }
    }
}
公共类PassByReference{
公共静态整数公司(整数i){
i=i+1;//我想这一定是**偷偷地**创建一个新的整数。。。
系统输出打印项次(“Inc:+i”);
返回i;
}
公共静态void main(字符串[]args){
整数=新整数(0);

对于(int i=0;i有两个问题:

  • 整数是按值传递的,而不是按引用传递的。更改方法内的引用不会反映到调用方法中传入的引用中
  • 整数是不可变的。没有像
    Integer#set(i)
    这样的方法。否则,您可以直接使用它
  • 要使其工作,需要重新分配
    inc()
    方法的返回值

    integer = inc(integer);
    

    要了解有关按值传递的更多信息,请参见另一个示例:

    public static void main(String... args) {
        String[] strings = new String[] { "foo", "bar" };
        changeReference(strings);
        System.out.println(Arrays.toString(strings)); // still [foo, bar]
        changeValue(strings);
        System.out.println(Arrays.toString(strings)); // [foo, foo]
    }
    public static void changeReference(String[] strings) {
        strings = new String[] { "foo", "foo" };
    }
    public static void changeValue(String[] strings) {
        strings[1] = "foo";
    }
    

    我想是自动包装把你甩了

    这部分代码:

       public static Integer inc(Integer i) {
            i = i+1;    // I think that this must be **sneakally** creating a new integer...  
            System.out.println("Inc: "+i);
            return i;
        }
    
    Integer i = 0;
    i = i + 1;  
    
    实际上可以归结为如下代码:

      public static Integer inc(Integer i) {
            i = new Integer(i) + new Integer(1);      
            System.out.println("Inc: "+i);
            return i;
        }
    
    这当然不会更改传入的引用

    你可以用这样的东西来修复它

      public static void main(String[] args) {
            Integer integer = new Integer(0);
            for (int i =0; i<10; i++){
                integer = inc(integer);
                System.out.println("main: "+integer);
            }
        }
    
    publicstaticvoidmain(字符串[]args){
    整数=新整数(0);
    
    对于(int i=0;i您在这里看到的不是重载的
    +
    运算器,而是自动装箱行为。
    Integer
    类是不可变的,您的代码:

       public static Integer inc(Integer i) {
            i = i+1;    // I think that this must be **sneakally** creating a new integer...  
            System.out.println("Inc: "+i);
            return i;
        }
    
    Integer i = 0;
    i = i + 1;  
    
    编译器(在自动装箱之后)将其视为:

    因此,您的结论是正确的,
    Integer
    实例被更改了,但不是偷偷摸摸的-这与Java语言定义一致:-)

    如果您将inc()函数更改为

     public static Integer inc(Integer i) {
          Integer iParam = i;
          i = i+1;    // I think that this must be **sneakally** creating a new integer...  
          System.out.println(i == iParam);
          return i;
      }
    
    然后您将看到它总是打印“false”。 这意味着加法将创建Integer的一个新实例,并将其存储在局部变量i(“local”,因为i实际上是传递的引用的副本)中,使调用方法的变量保持不变

    Integer是一个不可变的类,这意味着您不能更改它的值,但必须获得一个新实例。在这种情况下,您不必像这样手动执行:

    i = new Integer(i+1); //actually, you would use Integer.valueOf(i.intValue()+1);
    

    相反,它是通过自动装箱完成的。

    整数是不可变的。您可以在自定义包装器类中包装int

    class WrapInt{
        int value;
    }
    
    WrapInt theInt = new WrapInt();
    
    inc(theInt);
    System.out.println("main: "+theInt.value);
    
    你在这里是正确的:

    Integer i = 0;
    i = i + 1;  // <- I think that this is somehow creating a new object!
    
    整数i=0;
    
    i=i+1;//通过引用传递有两种方法

  • 从Apache Commons库中使用
  • 创建自定义类,如下所示
  • 下面是执行此操作的示例代码:

    public class Test {
        public static void main(String args[]) {
            Integer a = new Integer(1);
            Integer b = a;
            Test.modify(a);
            System.out.println(a);
            System.out.println(b);
    
            IntegerObj ao = new IntegerObj(1);
            IntegerObj bo = ao;
            Test.modify(ao);
            System.out.println(ao.value);
            System.out.println(bo.value);
        }
    
    
        static void modify(Integer x) {
            x=7;
        }
        static void modify(IntegerObj x) {
            x.value=7;
        }   
    }
    
    class IntegerObj {
        int value;
        IntegerObj(int val) {
            this.value = val;
        }
    }
    
    输出:

    1
    1
    7
    7
    

    上面的回答很好,解释了OP中的实际问题

    如果任何人需要传递需要全局更新的数字,请使用
    AtomicInteger(
    ),而不是创建建议的各种包装类或依赖第三方LIB

    AtomicInteger(
    )当然主要用于线程安全访问,但是如果性能没有问题,为什么不使用这个内置类呢?当然,额外的好处是明显的线程安全性

    import java.util.concurrent.atomic.AtomicInteger
    
    1)只有引用的副本作为值发送给形式参数。当形式参数变量被赋予其他值时,形式参数的引用将更改,但实际参数的引用在该整数对象中保持不变

    公共类理解对象{

    public static void main(String[] args) {
    
        Integer actualParam = new Integer(10);
    
        changeValue(actualParam);
    
        System.out.println("Output " + actualParam); // o/p =10
    
        IntObj obj = new IntObj();
    
        obj.setVal(20);
    
        changeValue(obj);
    
        System.out.println(obj.a); // o/p =200
    
    }
    
    private static void changeValue(Integer formalParam) {
    
        formalParam = 100;
    
        // Only the copy of reference is set to the formal parameter
        // this is something like => Integer formalParam =new Integer(100);
        // Here we are changing the reference of formalParam itself not just the
        // reference value
    
    }
    
    private static void changeValue(IntObj obj) {
        obj.setVal(200);
    
        /*
         * obj = new IntObj(); obj.setVal(200);
         */
        // Here we are not changing the reference of obj. we are just changing the
        // reference obj's value
    
        // we are not doing obj = new IntObj() ; obj.setValue(200); which has happend
        // with the Integer
    
    }
    
    }

    类IntObj{ 整数a

    public void setVal(int a) {
        this.a = a;
    }
    

    }

    它不是真正的按值传递。它是引用的按值传递…因为对象唯一要传递的是内存地址。严格来说,对于引用是“按值传递引用”,对于原语是“按值传递引用”。那么,一个引用副本被发送到函数中。发送到函数的引用副本与发送到函数的引用有何不同?有什么显著的区别吗?BalusC已经搞定了,但这里有一个简单的解释。Java发送一个在函数堆栈上创建的引用副本。行字符串=新字符串[]{“foo”,“foo”};修改在changeReference(String[])本地堆栈上创建的引用的副本。调用函数main()会知道在其自身堆栈上创建的引用(而不是在changeReference()堆栈上创建的引用).huh,好吧,这很有趣。感谢自动装箱术语。不可变似乎也很关键。祝你周末愉快!你可以查看自动装箱。回到Java 1.4,你只能添加带整数的整数,或者带整数的整数。现在,你可以以任何方式做的事情都有点难以概念化,只看代码。相关问题:为什么是整数是否设置为不可变?@RahulJain不确定,我怀疑它与实际值类型(
    int
    )一致,所以它们都有相同的语义。一致性是什么意思?int可以更改,但不能是整数,这是包装类的一个缺点。@RahulJain
    int
    是一个
    基本类型。基本类型是不可变的。我怀疑你把不可变性和
    final
    关键字混淆了-它们是不同的东西。你可以更改
    Integer
    变量的引用(与
    int
    变量的值相同)。它们非常一致。性能如何,它是否完好无损?显然,如果只需要
    AtomicInteger
    通过引用传递,则线程安全不需要它。性能似乎与Integer相同(假设您只使用.set(),.get(),并且没有使用任何线程安全操作)。
    public void setVal(int a) {
        this.a = a;
    }