【问题标题】:How to use Pass by Value in Java如何在 Java 中使用按值传递
【发布时间】:2011-09-10 19:30:24
【问题描述】:
public class Test {

        public void Receiving (int var)
        {
          var = var + 2;
        }

        public static void main(String [] args)
        {
          int passing = 3;

          Receiving (passing);

          System.out.println("The value of passing is: " +passing);
        }    
    }

当我编译这段代码时......我得到了这个错误。

Test.java:12: non-static method Receiving(int) cannot be referenced from a static context
  Receiving (passing);
  ^

现在,当我将接收方法更改为static 时,输出为....

The value of passing is: 3

现在我如何将值 3 传递给 Receiving 方法,以便在控制台中打印输出 5。

【问题讨论】:

标签: java pass-by-reference pass-by-value


【解决方案1】:

这在 Java 中通常是不可能的,因为原始类型总是按值传递,而不是按引用传递。即使您使用Integer 包装类而不是int,也无法更改它,因为Integer 是不可变的。

不过你可以使用这个技巧:

public class Test {

    // static is necessary, as you already found out
    public static void Receiving (int[] var)
    {
      var[0] = var[0] + 2;
    }

    public static void main(String [] args)
    {
      int[] passing = new int[] {3};
      Receiving (passing);
      System.out.println("The value of passing is: " +passing[0]);
    }    
}

【讨论】:

  • 所有类型都按值传递
  • 所有类型要么是原始类型,要么是引用类型。原语是按值传递的。引用是按值传递的。查看其他答案
  • @newacct:好的,是的。我知道。如果您认为其中缺少此信息,您可以更正我的答案。我认为这是关于原始类型(OP 的问题),所以我没有深入 JLS
【解决方案2】:

这不是 pass-by-value,而是 pass-by-reference!值传递实际上意味着该方法适用于原始变量的副本。 (见http://en.wikipedia.org/wiki/Evaluation_strategy)。 Java 总是按值传递。

对于原始类型(例如intfloat等),如果你想通过方法修改输入值,你可以简单地返回它:

public static int Receiving(int var) {
    return var + 2;
}

...

passing = Receiving(passing);

【讨论】:

    【解决方案3】:

    Java 是按值传递的,但您必须清楚传递的是什么:它是对对象或值的引用,而不是对象或值本身。您无法修改该引用,但您可以更改它指向的对象的状态(只要它是可变的)。

    所以您永远不会在控制台中看到输出“5”。 Java 不是这样工作的。 JVM已经说清楚了。

    【讨论】:

      【解决方案4】:

      现在我如何将值 3 传递给 接收方法使得 输出是 5 打印在控制台中。

      您可以包装整数,以便将其作为引用传递:

      public class Test {
      
          class Wrapper {
              int var;
      
              Wrapper(int val) {
                  var = val;
              }
          }
      
          public void Receiving(Wrapper w) {
              w.var = w.var + 2;
          }
      
          public static void main(String[] args) {
              Test test = new Test();
              Wrapper passing = test.new Wrapper(3);
              test.Receiving(passing);
              System.out.println("The value of passing is: " + passing.var);
          }
      }
      

      【讨论】:

        【解决方案5】:

        不能用“int”来做——Java 中只有“pass-by-value”。不过,可以使用 AtomicInteger 轻松模拟:

        static void test(AtomicInteger i)
        {
            i.addAndGet(2);
        }
        
        public static void main(String[] args) throws IOException
        {
            AtomicInteger i = new AtomicInteger(3);
            test(i);
            System.out.println(i);
        }
        

        【讨论】:

          【解决方案6】:

          只能在对象实例上调用非静态成员函数。它不能“单独”调用。

          你有两个选择:

          1. 使Receiving静态;
          2. 在 main 中创建 Test 的实例并调用 test.Receiving(3)

          无论哪种方式,var 都会按值传递给函数,因此main 将看不到更改后的值。为了解决这个问题,您有多种选择,其中包括:

          1. var 变成一个单元素数组,
          2. 使用AtomicInteger(它并不是为此而设计的,但我经常看到它以这种方式使用)。

          【讨论】:

            【解决方案7】:

            在 Java 中调用者通常更清楚地使用函数,因为您应该期望方法更改对象而不是其参数。

            public static int receiving (int var) {
                return var + 2;
            }
            
            public static void main(String... args){
                int passing = 3;
                // its clear passing can be changed.
                passing = receiving(passing); 
                System.out.println("The value of passing is: " +passing);
            }   
            

            【讨论】:

              【解决方案8】:

              原始类型是按值传递的。 Java 对象总是被引用,并且它的引用总是按值传递。

              对于静态错误,有两种解决方法:

              1. 制作receivingstatic,或者:
              2. 创建一个Test 对象并调用receiving

              例子:

              Test test = new Test();
              test.Receiving(passing);
              

              要通过引用传递,您必须将对象的引用传递给方法(java 将通过值传递引用)并从那里进行计算。一个 int 或 AtomicInteger 的数组就可以了。

              【讨论】:

                【解决方案9】:

                上面别人说的很对。 但是,如果您只想获得 5 作为最终输出,那么有很多方法可以实现这一目标。我已经在其中一个下面发布了。

                public class NewClass {
                
                     static int passing = 3;
                
                    public static void Receiving (int var)
                    {
                      var = var + 2;
                      passing = var;
                    }
                
                    public static void main(String [] args)
                    {
                
                      Receiving (passing);
                
                      System.out.println("The value of passing is: " +passing);
                    }
                

                }

                我知道这不是一个好方法,但我觉得你一心想要打印 5 个......

                【讨论】:

                  【解决方案10】:

                  在 Java 中无法通过引用传递,并且根本不传递对象:Article on passing

                  你可以

                  1. 在函数中使用返回值并在主程序中使用该值
                  2. 在顶部声明一个静态值。那么您的价值将具有整个程序的范围,但不确定您是否想要那个

                  【讨论】:

                  • 为了挑剔,引用也不可能。
                  • 啊,我明白你的意思了,谢谢!我将编辑帖子以更准确。 :)
                  猜你喜欢
                  • 2014-09-10
                  • 2016-05-29
                  • 2021-11-04
                  • 2016-11-28
                  • 2013-12-02
                  相关资源
                  最近更新 更多