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

什么是解释?


当前回答

第二步,请记住,当您将对象转移到一种方法时,您将转移到对象参考,而不是对象本身。

现在,想想一个对象的参考/变量是什么:

1. Person person;
2. person = new Person("Tom");
3. changeName(person);
4.
5. //I didn't use Person person below as an argument to be nice
6. static void changeName(Person anotherReferenceToTheSamePersonObject) {
7.     anotherReferenceToTheSamePersonObject.setName("Jerry");
8. }

发生了什么?

变量人是创建的行 #1 它是零的开始. 一个新人对象是创建的行 #2,存储在记忆中,变量人是给予的参考人对象. 也就是说,其地址. 让我们说 3bad086a. 保持对象的地址的变量人是转移到函数行 #3. 在行 #4 你可以听到沉默的声音 查看其地址。

一张照片值得一千个字:

此分類上一篇

请注意,另一个ReferenceToTheSamePersonObject射线是指向对象而不是变量人!

您总是输入参考值的比特的副本!

Java 是 pass-by-value 因为在一个方法中,你可以随心所欲地修改所提到的对象,但无论你尝试多么艰难,你永远不会能够修改过去的变量,这将保持参考(不 p _ _ _ _ _ _ _ )相同的对象,不管是什么!



其他回答

Java 总是使用 Call by Value. 这意味着该方法获得所有参数值的副本。

考虑下列三种情况:

1、试图改变原始变量

public static void increment(int x) { x++; }

int a = 3;
increment(a);

x 将复制一个值,并将增加 x,一个将保持相同的值

(二)试图改变对象的原始领域

public static void increment(Person p) { p.age++; }

Person pers = new Person(20); // age = 20
increment(pers);

p 将复制个体的参考值,并将增加年龄领域,变量是指相同的对象,所以年龄改变。

(三)试图改变参考变量的参考值

public static void swap(Person p1, Person p2) {
    Person temp = p1;
    p1 = p2;
    p2 = temp;
}

Person pers1 = new Person(10);
Person pers2 = new Person(20);
swap(pers1, pers2);

呼叫交换 p1 后,p2 复制 pers1 和 pers2 的参考值与值交换,因此 pers1 和 pers2 仍然相同。

因此,您只能在将参考值复制到该对象时更改对象的字段。

Pass By Reference 收到的函数值是通话者所使用的对象的参考。 通话者所指的对象的任何函数都将被通话者看到,并将从那时起与这些变化进行操作。

正如这些定义所表明的那样,参考通过值是毫无意义的,如果我们要接受这个定义,那么这些术语就变得毫无意义,所有语言都只是通过值。

因此,有了这个理解,我们可以看看Java,并看到它实际上有两种。所有Java原始类型总是通过值,因为你收到一个复印件的呼叫器的对象,并且不能修改他们的复印件。

Java 使用 pass-by-value,但效果不同的是你是否使用原始或参考类型。

当你将原始类型作为论点转移到一种方法时,它将获得原始类型的副本,而方法块内的任何变化都不会改变原始变量。

当您将参考类型作为一个论点转移到一个方法时,它仍然得到一个副本,但它是对对象的参考的副本(换句话说,您正在获得记忆地址的副本在对象所在地),因此对象中的任何变化在方法的区块内将影响原始对象在区块外。

我认为这个简单的解释可以帮助你理解,因为我想在我正在争论这一点时理解这一点。

当您将原始数据传输到函数呼叫时,其内容将复制到函数的论点,当您传输一个对象时,其参考将复制到函数的论点。

考虑到这个简单的例子,线条是Java的对象,当你改变一个线条的内容时,参考变量现在将指向一些新的参考,因为线条对象在Java中是不可变的。

String name="Mehrose";  // name referencing to 100

ChangeContenet(String name){
 name="Michael"; // refernce has changed to 1001

} 
System.out.print(name);  //displays Mehrose

很简单,因为正如我提到的那样,您不允许在呼叫函数中更改复制的参考,但问题在于当您通过 String/Object 序列时,该序列。

String names[]={"Mehrose","Michael"};

changeContent(String[] names){
  names[0]="Rose";
  names[1]="Janet"

}

System.out.println(Arrays.toString(names)); //displays [Rose,Janet]

你不能这样做

Student student1= new Student("Mehrose");

changeContent(Student Obj){
 obj= new Student("Michael") //invalid
 obj.setName("Michael")  //valid

}

在这里,每一个单一的答案都倾向于从其他语言中提到通过指标,并显示在Java中不可能做什么,因为任何原因,没有人试图从其他语言中展示如何实施通过对象的价值。

这个代码表明如何做这样的事情:

public class Test
{
    private static void needValue(SomeObject so) throws CloneNotSupportedException
    {
        SomeObject internalObject = so.clone();
        so=null;
        
        // now we can edit internalObject safely.
        internalObject.set(999);
    }
    public static void main(String[] args)
    {
        SomeObject o = new SomeObject(5);
        System.out.println(o);
        try
        {
            needValue(o);
        }
        catch(CloneNotSupportedException e)
        {
            System.out.println("Apparently we cannot clone this");
        }
        System.out.println(o);
    }
}

public class SomeObject implements Cloneable
{
    private int val;
    public SomeObject(int val)
    {
        this.val = val;
    }
    public void set(int val)
    {
        this.val = val;
    }
    public SomeObject clone()
    {
        return new SomeObject(val);
    }
    public String toString()
    {
        return Integer.toString(val);
    }
}

在这里,我们有一个函数需要值,它正在立即创建一个对象的克隆,需要在对象本身的类中实施,而该类必须被标记为克隆。

可能很好,Java没有通过参考语法,但称之为“通过价值”的语言沿着有愿望的思维线。