【问题标题】:Pass by value or Pass by reference in Java?Java中的值传递还是引用传递?
【发布时间】:2011-11-10 05:25:57
【问题描述】:

我阅读了很多文章,都说 Java 是按值传递的。但是我仍然不解释按值传递和引用之间的区别。我写了一个示例程序,它是这样执行的..

public class PassByValue {

   private int a;
   private int b;

   public PassByValue(int a, int b) {
    this.a = a;
    this.b = b;
   }

   public static int mul(int a, int b) {

       int z = a * b;
       System.out.println("The Value of Z inside mul: " + z);
       return z;

   }

   public static void main(String args[]) {

    int z = 100;

        int x = 40;
        int y = 20;

    mul(x,y);

    PassByValue pass = new PassByValue(x,y);
    mul(pass.a,pass.b);

        System.out.println("The Value of Z" + z);

   }

}

执行

800
800 and 
100

谁能解释我这些问题...

  1. 什么是按值传递意味着...

答案:它只是将存储在变量中的数字或值传递给函数。我是对还是错。

  1. Java 是按值传递的怎么说?
  2. 为什么 Java 是按值传递而不是按引用传递?
  3. 上述程序 Tries 是否显示了按值传递和引用的示例...但仍然仅通过按值传递来执行操作...我编写了该程序。

【问题讨论】:

标签: java


【解决方案1】:

混淆可能是由于变量首先不能包含对象。一个变量只能包含一个对象的引用。 (换句话说,对象根本不被传递,不是通过引用,也不是通过值。)

一旦您意识到这一点,就很清楚在 Java 中没有什么是通过引用传递的。引用对象的变量存储一个引用,这个引用是按值传递的。


1.什么是按值传递意味着...

答案:它只是将存储在变量中的数字或值传递给函数。我是对还是错。

没错。传递的是变量中包含的,而不是变量本身。

1. Java 是如何传递价值的?

Java 是按值传递的,因为原语是按值传递的,而引用是按值传递的。 (对象永远不会传递。)

例如,您不能在 Java 中实现 swap 方法。也就是说,你不能这样做

String str1 = "hello";
String str2 = "world";
swap(str1, str2);
// str1 can't refer to anything but "hello"
// str2 can't refer to anything but "world"

2.为什么 Java 是按值传递而不是按引用传递?

如上所述,即使是引用也是按值传递的。

【讨论】:

    【解决方案2】:

    您可以将按值传递视为仅传递变量中包含的值,而不传递变量本身。然后将该值复制到另一个临时变量中。相比之下,您可以将按引用传递视为传递实际变量并且不制作临时副本,因此变量中的任何更改都被“保存”。尽管还有更多内容,但考虑它可能更容易

    【讨论】:

      【解决方案3】:

      你的答案是对的,但你缺乏细节。如果你这样做了

      Dog d = new Dog()

      d 是对 Dog 实例的引用,即按值传递的意思是您将 d 传递给方法时

      walkDog(d);

      对 Dog 的引用(即引用的值,而不是引用本身)的 副本 被传递到方法中。因此,您有 2 个对 Dog 的一个实例的引用,一个在调用范围内,一个在被调用范围内。假设在walkDog 方法中有一行

      d = new Dog();

      仅方法中的d 引用指向新的Dog。最初调用该方法的原始引用仍然指向original Dog。如果 Java 通过引用传递,相同的引用,而不是引用的副本将在方法中使用,因此更改引用的值会影响调用和被调用中的引用范围。

      编辑——根据您的评论,我想澄清一下。由于原始范围内的引用和方法范围都指向 same 对象,因此您仍然可以在两个范围内更改该对象上的内容。所以如果你这样做了

      d.drinkWater();

      walkDog 方法中,drinkWater 更改了 dog 对象上的某些变量,然后由于两个引用指向同一个对象,因此该对象已更改。

      这只是 references 在每个范围内实际存在的区别。但它确实出现了很多。

      【讨论】:

      • hvgotcodes:谢谢......完美的解释......如果我错了,请纠正我,我没有发送原始变量或对我的函数的引用......而是一个副本......所以价值确实只在那个范围内改变,而不是在每一个地方......
      • 所以复制引用和原始引用指向相同的地址位置......但指向不同的 DOG 实例。
      • @theJava,没有 2 个引用指向同一只狗。更改其中一个引用不会更改另一个引用,但使用任一引用更改对象会更改同一个对象。
      • 对于 C 语言的人:它的功能等同于在 C 中传递一个指针,然后在进入函数后立即复制该指针以在函数中使用。除非您在函数中更改指针的值,否则指针指向的数据是相同的。
      • @hvgotcodes 为什么字符串在传递给方法时不会改变?它们是对象,而不是原始数据类型。
      【解决方案4】:

      我认为,如果 Java 支持通过引用或值传递,我认为应该清楚在他的实现中使用 Java 中类的实例的方式。这一切都恰好是实例的类型——可变/不可变,这将决定我们将事物传递给函数的方式!由您来探索这种差异!

      让我澄清一下我的论点,为什么没有必要追赶经过什么?!考虑这个... 第一个代码:

          void foobar(int *a){
              printf("%d", *a);
          }
      
          int main(){
              int a = 5;
              foobar(&a);
              return 0;
          }
      

      在这段 C 代码中,你在传递什么……变量“a”的地址。这恰好是通过引用传递! :)

      让我们考虑另一个... 第二个代码:

          void foobar(int* a){
              printf("%d", *a);
          }
      
          int main(){
              int a = 5;
              int *p = &a;
              foobar(p);
              return 0;
          }
      

      在这段 C 代码中,我在传递什么......?变量'p'的值,不管它是指针还是其他东西:P

      那么,您如何将其称为按值传递/按引用传递?我把这个留给你!但我们只需要看看我们将如何实现...... :)

      所以在 Java 中......我们可以说 - 它支持“按值传递”或“通过某些实例的引用传递”而不是“按引用传递”

      ***我能清楚地得出结论的是Java中的原始数据类型。由于没有指针可以在没有实际变量的情况下编辑字节的内容,因此我们不能在 Java 中通过引用传递它们(我的意思是原始数据类型)。

      【讨论】:

        猜你喜欢
        • 2016-11-28
        相关资源
        最近更新 更多