我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。

什么是解释?


当前回答

在所有的答案中,我们看到Java通过价值,或者正如Gevorg所写的那样:“通过复制变量的价值”,这就是我们应该始终记住的想法。

在Java中,你总是通过复制论点,即你总是在函数中创建一个新的值例子,但有些行为会让你认为你正在通过参考。

此分類上一篇: [ref 1]

void incrementValue(int inFunction){
  inFunction ++;
  System.out.println("In function: " + inFunction);
}

int original = 10;
System.out.print("Original before: " + original);
incrementValue(original);
System.out.println("Original after: " + original);

We see in the console:
 > Original before: 10
 > In Function: 11
 > Original after: 10 (NO CHANGE)

以 [ref 2] 的例子

顯示優雅的機制觀點 max 5 min

(按参考通行) pass-by-copy-of-the-variable-值

void incrementValu(int[] inFuncion){
  inFunction[0]++;
  System.out.println("In Function: " + inFunction[0]);
}

int[] arOriginal = {10, 20, 30};
System.out.println("Original before: " + arOriginal[0]);
incrementValue(arOriginal[]);
System.out.println("Original before: " + arOriginal[0]);

We see in the console:
  >Original before: 10
  >In Function: 11
  >Original before: 11 (CHANGE)

复杂物体本身正在复制,但内部参考正在保持。

此分類上一篇: [ref 3]

package com.pritesh.programs;

class Rectangle {
  int length;
  int width;

  Rectangle(int l, int b) {
    length = l;
    width = b;
  }

  void area(Rectangle r1) {
    int areaOfRectangle = r1.length * r1.width;
    System.out.println("Area of Rectangle : " 
                            + areaOfRectangle);
  }
}

class RectangleDemo {
  public static void main(String args[]) {
    Rectangle r1 = new Rectangle(10, 20);
    r1.area(r1);
  }
}

我想分享的最后一件事是讲座的这个时刻:记忆分配,我认为它非常有用,以了解Java通过值或更为“通过复制变量的值”如Gevorg所写的。

其他回答

在Java中,你永远不会通过参考,而一个显而易见的方式是当你想从一个方法通话中返回超过一个值时。

void getValues(int& arg1, int& arg2) {
    arg1 = 1;
    arg2 = 2;
}
void caller() {
    int x;
    int y;
    getValues(x, y);
    cout << "Result: " << x << " " << y << endl;
}

有时你想在Java中使用相同的模式,但你不能;至少不是直接。

void getValues(int[] arg1, int[] arg2) {
    arg1[0] = 1;
    arg2[0] = 2;
}
void caller() {
    int[] x = new int[1];
    int[] y = new int[1];
    getValues(x, y);
    System.out.println("Result: " + x[0] + " " + y[0]);
}

正如以前的答案中所解释的那样,在Java中,你将一个指标转移到序列作为一个值进入 getValues. 这就足够了,因为方法然后改变序列元素,并且通过协议,你期望元素 0 包含回报值。

我在这里创建了一个专门为任何编程语言提出这些问题的条纹。

Java 也被提及,这里是简短的概述:

Java 通过它的参数值“值”是Java 唯一的方式将一个参数转换为一个方法,使用从所提供的对象作为参数的方法将改变对象,因为参考指向原始对象(如果该方法本身改变某些值)。

Java 是由價值通過的。

在某种程度上,我从来没有透露过原始数据类型和对象的值/参考。因此,我用下列代码来测试我的满意度和清晰度;可能有助于寻求类似清晰度的人:

class Test    {

public static void main (String[] args) throws java.lang.Exception
{
    // Primitive type
    System.out.println("Primitve:");
    int a = 5;
    primitiveFunc(a);
    System.out.println("Three: " + a);    //5

    //Object
    System.out.println("Object:");
    DummyObject dummyObject = new DummyObject();
    System.out.println("One: " + dummyObject.getObj());    //555
    objectFunc(dummyObject);
    System.out.println("Four: " + dummyObject.getObj());    //666 (555 if line in method uncommented.)

}

private static void primitiveFunc(int b)    {
    System.out.println("One: " + b);    //5
    b = 10;
    System.out.println("Two:" + b);    //10
}

private static void objectFunc(DummyObject b)   {
    System.out.println("Two: " + b.getObj());    //555
    //b = new DummyObject();
    b.setObj(666);
    System.out.println("Three:" + b.getObj());    //666
}

}

class DummyObject   {
    private int obj = 555;
    public int getObj() { return obj; }
    public void setObj(int num) { obj = num; }
}

如果行 b = 新 DummyObject() 没有评论,随后进行的修改是在一个新的对象,一个新的实例上进行的。 因此,它不反映在方法被召回的地方。 但是,否则,变化是反映的,因为修改只是在对象的“参考”上进行的,即 - b 点到相同的 dummyObject。

在这个条纹中的答案之一(https://stackoverflow.com/a/12429953/4233180)的描述可以帮助获得更深入的理解。

Java 以價值通過一切!!!

创建一个对象,通过一个名字和年龄:

PersonClass variable1 = new PersonClass("Mary", 32);

PersonClass variable2;

// 变量2 和变量1 现在提到相同的对象

variable2 = variable1; 


PersonClass variable3 = new PersonClass("Andre", 45);

// variable1 现在指向 variable3

variable1 = variable3;

什么是由此产生的?

System.out.println(variable2);
System.out.println(variable1);

Mary 32
Andre 45

如果你能理解这个例子,我们做了,否则,请访问这个网页详细解释:

网页

只需显示对比,请比较以下 C++ 和 Java 剪辑:

在 C++ 中: 注意: 坏代码 - 记忆泄漏! 但它证明了这一点。

void cppMethod(int val, int &ref, Dog obj, Dog &objRef, Dog *objPtr, Dog *&objPtrRef)
{
    val = 7; // Modifies the copy
    ref = 7; // Modifies the original variable
    obj.SetName("obj"); // Modifies the copy of Dog passed
    objRef.SetName("objRef"); // Modifies the original Dog passed
    objPtr->SetName("objPtr"); // Modifies the original Dog pointed to 
                               // by the copy of the pointer passed.
    objPtr = new Dog("newObjPtr");  // Modifies the copy of the pointer, 
                                   // leaving the original object alone.
    objPtrRef->SetName("objRefPtr"); // Modifies the original Dog pointed to 
                                    // by the original pointer passed. 
    objPtrRef = new Dog("newObjPtrRef"); // Modifies the original pointer passed
}

int main()
{
    int a = 0;
    int b = 0;
    Dog d0 = Dog("d0");
    Dog d1 = Dog("d1");
    Dog *d2 = new Dog("d2");
    Dog *d3 = new Dog("d3");
    cppMethod(a, b, d0, d1, d2, d3);
    // a is still set to 0
    // b is now set to 7
    // d0 still have name "d0"
    // d1 now has name "objRef"
    // d2 now has name "objPtr"
    // d3 now has name "newObjPtrRef"
}

在Java,

public static void javaMethod(int val, Dog objPtr)
{
   val = 7; // Modifies the copy
   objPtr.SetName("objPtr") // Modifies the original Dog pointed to 
                            // by the copy of the pointer passed.
   objPtr = new Dog("newObjPtr");  // Modifies the copy of the pointer, 
                                  // leaving the original object alone.
}

public static void main()
{
    int a = 0;
    Dog d0 = new Dog("d0");
    javaMethod(a, d0);
    // a is still set to 0
    // d0 now has name "objPtr"
}

Java 只有兩種通過: 根據內置類型的價值,並根據對象類型的指標的價值。