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

什么是解释?


当前回答

例如,使用 badSwap() 方法:

public void badSwap(int var1, int var2)
{
  int temp = var1;
  var1 = var2;
  var2 = temp;
}

当 badSwap() 返回时,作为论点过渡的变量将仍然保持其原始值。 该方法也会失败,如果我们将论点类型从 int 转换为 对象,因为 Java 通过对象参考值也。

public void tricky(Point arg1, Point arg2)
{
  arg1.x = 100;
  arg1.y = 100;
  Point temp = arg1;
  arg1 = arg2;
  arg2 = temp;
}
public static void main(String [] args)
{
  Point pnt1 = new Point(0,0);
  Point pnt2 = new Point(0,0);
  System.out.println("X: " + pnt1.x + " Y: " +pnt1.y); 
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
  System.out.println(" ");
  tricky(pnt1,pnt2);
  System.out.println("X: " + pnt1.x + " Y:" + pnt1.y); 
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);  
}

如果我们执行这个主要()方法,我们会看到以下输出:

X: 0 Y: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0

图1 转移到一个方法后,对象将至少有两种参考。

Java 复制并通过参考值,而不是对象. 因此,方法操作将改变对象,因为参考指向原始对象. 但是,因为参考是复制,交换将失败。 方法参考交换,但不是原始参考。 不幸的是,在一个方法呼叫后,你只剩下未交换的原始参考。

其他回答

主要的角石知识必须是引用的一个,

当对象引用转移到一种方法时,引用本身通过使用呼叫值。 但是,因为引用的值是指对象,则该值的副本仍然是指其相应论点所引用的相同对象。

Java: A Beginner's Guide 第六版 希尔伯特·希尔德

很难理解,但Java总是复制值 - 点是,通常值是参考。

Java 以值复制参考,因此,如果您将其更改为另一个(例如,使用新)则参考不会在方法之外更改。

参考是常见的值,无论你使用哪种语言。

(Name)[Location] -> [Value at the Location]
---------------------
(Ref2Foo)[223]  -> 47
(Foo)[47]       -> 5

这就是跳板的工作方式。

在每个例子上创建了一个值 - 一个现有值的副本 - 现在是接收方法来处理它. 当你写“Foo”在方法,它是从EAX,或者自动右转,或双右转,过程取决于语言如何工作和 / 或什么类型的Foo独裁。

现在我们把Foo转到方法:

因此,简而言之,在Java本身的术语中,Java是通过价值,在那里价值可以是:无论是真实的价值还是参考的价值。

讓我試圖用四個例子來解釋我的理解:Java是通過價值,而不是通過参考。

* * *

public class PassByValueString {
    public static void main(String[] args) {
        new PassByValueString().caller();
    }

    public void caller() {
        String value = "Nikhil";
        boolean valueflag = false;
        String output = method(value, valueflag);
        /*
         * 'output' is insignificant in this example. we are more interested in
         * 'value' and 'valueflag'
         */
        System.out.println("output : " + output);
        System.out.println("value : " + value);
        System.out.println("valueflag : " + valueflag);

    }

    public String method(String value, boolean valueflag) {
        value = "Anand";
        valueflag = true;
        return "output";
    }
}

output : output
value : Nikhil
valueflag : false

例子2:

/** * * Pass By 價值 */

public class PassByValueNewString {
    public static void main(String[] args) {
        new PassByValueNewString().caller();
    }

    public void caller() {
        String value = new String("Nikhil");
        boolean valueflag = false;
        String output = method(value, valueflag);
        /*
         * 'output' is insignificant in this example. we are more interested in
         * 'value' and 'valueflag'
         */
        System.out.println("output : " + output);
        System.out.println("value : " + value);
        System.out.println("valueflag : " + valueflag);

    }

    public String method(String value, boolean valueflag) {
        value = "Anand";
        valueflag = true;
        return "output";
    }
}

output : output
value : Nikhil
valueflag : false

/** 这个“通过价值”具有“通过参考”的感觉

但是,从这个例子,我们可以理解,它只是通过值,记住,在这里我们通过参考作为值. 也就是说:参考通过值. 这就是为什么它们可以改变,但它仍然保持在当地范围后真实。

public class PassByValueObjectCase1 {

    private class Student {
        int id;
        String name;
        public Student() {
        }
        public Student(int id, String name) {
            super();
            this.id = id;
            this.name = name;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "Student [id=" + id + ", name=" + name + "]";
        }
    }

    public static void main(String[] args) {
        new PassByValueObjectCase1().caller();
    }

    public void caller() {
        Student student = new Student(10, "Nikhil");
        String output = method(student);
        /*
         * 'output' is insignificant in this example. we are more interested in
         * 'student'
         */
        System.out.println("output : " + output);
        System.out.println("student : " + student);
    }

    public String method(Student student) {
        student.setName("Anand");
        return "output";
    }
}

结果

output : output
student : Student [id=10, name=Anand]

例子4:

* * *

除了在Example3(PassByValueObjectCase1.java)中提到的外,我们不能在原始范围之外更改实际参考。

注意: 我不符合私人课堂学生的代码. 学生的课堂定义与例子3相同。

public class PassByValueObjectCase2 {

    public static void main(String[] args) {
        new PassByValueObjectCase2().caller();
    }

    public void caller() {
        // student has the actual reference to a Student object created
        // can we change this actual reference outside the local scope? Let's see
        Student student = new Student(10, "Nikhil");
        String output = method(student);
        /*
         * 'output' is insignificant in this example. we are more interested in
         * 'student'
         */
        System.out.println("output : " + output);
        System.out.println("student : " + student); // Will it print Nikhil or Anand?
    }

    public String method(Student student) {
        student = new Student(20, "Anand");
        return "output";
    }

}

output : output
student : Student [id=10, name=Nikhil]