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

什么是解释?


当前回答

我遇到了类似的问题. 这个关于圈子的故事对我来说是一个具体的答案. 我想添加到答案. 希望它能帮助那些有类似问题的人。

https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html

在方法中,循环起初指 myCircle. 该方法改变了对象的 x 和 y 坐标,循环参考(即 myCircle)为 23 和 56, 相应. 这些变化将持续,当方法返回. 然后循环被分配一个参考一个新的循环对象与 x = y = 0. 这个重新分配没有永久性, 但是,因为参考通过了值

其他回答

数据通过参数在函数之间共享,现在有两种方式通过参数:

通过参数 : 呼叫器和呼叫器使用相同的变量为参数. 通过值 : 呼叫器和呼叫器有两个独立的变量与相同的值。

Java 使用 Pass by Value

在传输原始数据时,它复制原始数据类型的值;在传输对象时,它复制对象的地址,并转移到转换方法变量。

Java 在存储变量中遵循以下规则:

原始和对象参考等本地变量在 Stack 记忆中创建,对象在 Heap 记忆中创建。

使用原始数据类型的例子:

public class PassByValuePrimitive {
    public static void main(String[] args) {
        int i=5;
        System.out.println(i);  //prints 5
        change(i);
        System.out.println(i);  //prints 5
    }
    
    
    private static void change(int i) {
        System.out.println(i);  //prints 5
        i=10;
        System.out.println(i); //prints 10
        
    }
}

使用对象的例子:

public class PassByValueObject {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("prem");
        list.add("raj");
        new PassByValueObject().change(list);
        System.out.println(list); // prints [prem, raj, ram]
        
    }
    
    
    private  void change(List list) {
        System.out.println(list.get(0)); // prem
        list.add("ram");
        list=null;
        System.out.println(list.add("bheem")); //gets NullPointerException
    }
}

一般来说,Java有原始类型(int、bool、char、double等)直接通过值,然后Java有对象(所有来自java.lang.Object的一切)。对象实际上总是通过参考处理(一个参考是指标,你不能触摸)。这意味着实际上,对象通过参考,因为参考通常并不有趣。

事實的結論是,在「通過通過」的表達中,意思是完全不同於Java的常見意思。

但技术术语通过参考/值从编程语言理论是谈论一个参考到记忆细胞持有变量,这是一个完全不同的东西。

只需显示对比,请比较以下 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 只有兩種通過: 根據內置類型的價值,並根據對象類型的指標的價值。

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

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

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