是Java吗;参考传递”;或;传递值“;?

是Java吗;参考传递”;或;传递值“;?,java,methods,parameter-passing,pass-by-reference,pass-by-value,Java,Methods,Parameter Passing,Pass By Reference,Pass By Value,我一直认为Java使用按引用传递 然而,我看到一些博客文章(例如)声称它不是(博客文章说Java使用传递值) 我想我不明白他们的区别 原因是什么?Java总是按值传递,没有例外,从来都是 那么,怎么会有人对此感到困惑,认为Java是通过引用传递的,或者认为他们有一个Java作为通过引用传递的例子呢?关键的一点是Java从不提供在任何情况下直接访问对象本身的值。对对象的唯一访问是通过对该对象的引用。因为Java对象总是通过引用来访问,而不是直接访问,所以通常将字段、变量和方法参数称为对象,而从字面

我一直认为Java使用按引用传递

然而,我看到一些博客文章(例如)声称它不是(博客文章说Java使用传递值)

我想我不明白他们的区别


原因是什么?

Java总是按值传递,没有例外,从来都是

那么,怎么会有人对此感到困惑,认为Java是通过引用传递的,或者认为他们有一个Java作为通过引用传递的例子呢?关键的一点是Java从不提供在任何情况下直接访问对象本身的值。对对象的唯一访问是通过对该对象的引用。因为Java对象总是通过引用来访问,而不是直接访问,所以通常将字段、变量和方法参数称为对象,而从字面上讲,它们只是对对象的引用这种混淆源于这种(严格地说,是不正确的)命名变化。

因此,在调用方法时

  • 对于基元参数(
    int
    long
    等),传递值是基元的实际值(例如,3)
  • 对于对象,传递值是对对象的引用的值
因此,如果您有
doSomething(foo)
public void doSomething(foo foo){..}
两个foo复制了指向相同对象的引用


自然地,通过值传递对对象的引用与通过引用传递对象非常相似(在实践中没有区别)。

Java通过值传递引用

public class PassByCopy{
    public static void changeName(Dog d){
        d.name = "Fido";
    }
    public static void main(String[] args){
        Dog d = new Dog("Maxx");
        System.out.println("name= "+ d.name);
        changeName(d);
        System.out.println("name= "+ d.name);
    }
}
class Dog{
    public String name;
    public Dog(String s){
        this.name = s;
    }
}

因此,您无法更改传入的引用。

基本上,重新指定对象参数不会影响参数,例如

private void foo(Object bar) {
    bar = null;
}

public static void main(String[] args) {
    String baz = "Hah!";
    foo(baz);
    System.out.println(baz);
}

将打印出
“Hah!”
,而不是
null
。之所以这样做是因为
bar
baz
值的副本,它只是对
“哈!”
的引用。如果它是实际的引用本身,那么
foo
会将
baz
重新定义为
null

Java按值传递对对象的引用。

Java总是按值传递。不幸的是,当我们处理对象时,我们实际上是在处理被称为引用的对象句柄,这些句柄也是通过值传递的。这种术语和语义很容易使许多初学者感到困惑

public static void changeReference(Foo a)
事情是这样的:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    Dog oldDog = aDog;

    // we pass the object to foo
    foo(aDog);
    // aDog variable is still pointing to the "Max" dog when foo(...) returns
    aDog.getName().equals("Max"); // true
    aDog.getName().equals("Fifi"); // false
    aDog == oldDog; // true
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // change d inside of foo() to point to a new Dog instance "Fifi"
    d = new Dog("Fifi");
    d.getName().equals("Fifi"); // true
}
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]);
}
在上面的示例中,
aDog.getName()
仍将返回
“Max”
main
中的值
aDog
在函数
foo
中不会随
Dog
“Fifi”而改变,因为对象引用是通过值传递的。如果它是通过引用传递的,那么
main
中的
aDog.getName()
将在调用
foo
后返回
“fififi”

同样地:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    Dog oldDog = aDog;

    foo(aDog);
    // when foo(...) returns, the name of the dog has been changed to "Fifi"
    aDog.getName().equals("Fifi"); // true
    // but it is still the same dog:
    aDog == oldDog; // true
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // this changes the name of d to be "Fifi"
    d.setName("Fifi");
}

在上面的示例中,
Fifi
是调用
foo(aDog)
后狗的名字,因为对象的名字是在
foo(…)
中设置的。对于
foo
d
上执行的任何操作,实际上都是在
aDog
上执行的,但是不可能更改变量
aDog
本身的值。

长话短说,对象具有一些非常特殊的属性

一般来说,Java有直接通过值传递的基本类型(
int
bool
char
double
),等等。然后Java就有了对象(从
Java.lang.Object
派生的所有东西)。实际上,对象总是通过引用来处理的(引用是一个你不能触摸的指针)。这意味着实际上,对象是通过引用传递的,因为引用通常不感兴趣。但是,这确实意味着您不能更改指向哪个对象,因为引用本身是通过值传递的

这听起来是不是既奇怪又令人困惑?让我们考虑一下C是如何实现按引用传递和按值传递的。在C语言中,默认约定是按值传递<代码>无效foo(int x)按值传递int
void foo(int*x)
是一个函数,它不需要
inta
,而是指向int:
foo(&a)
。可以将其与
&
运算符一起使用,以传递变量地址


把这个带到C++,我们有参考文献。引用基本上是(在此上下文中)隐藏表达式指针部分的语法糖:

void foo(int&x)
foo(a)
调用,其中编译器本身知道它是引用,并且应该传递非引用
a
的地址。在java中,所有引用对象的变量实际上都是引用类型,实际上,通过引用来强制调用大多数目的和目的,而没有细粒度的控制(和复杂性),例如C++(

< p>)。或者,也许我记得,我曾经和最初的海报有着相同的印象,那就是:Java总是按值传递。Java中的所有对象(在Java中,除了原语以外的任何对象)都是引用。这些引用是按值传递的。

正如许多人之前提到的

下面是另一个帮助您理解差异()的示例:

印刷品:

之前:a=2,b=3
之后:a=2,b=3

这是因为iA和iB是新的局部引用变量,它们与传递的引用具有相同的值(它们分别指向a和b)。因此,尝试更改iA或iB的引用只会在本地范围内更改,而不会超出此方法。

我一直认为它是“通过复制”。它是原语值的副本
Dog myDog = new Dog("Rover");
foo(myDog);
public void foo(Dog someDog) {
    someDog.setName("Max");     // AAA
    someDog = new Dog("Fifi");  // BBB
    someDog.setName("Rowlf");   // CCC
}
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"
}
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"
}
void getValues(int& arg1, int& arg2) {
    arg1 = 1;
    arg2 = 2;
}
void caller() {
    int x;
    int y;
    getValues(x, y);
    cout << "Result: " << x << " " << y << endl;
}
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]);
}
public static void swap(StringBuffer s1, StringBuffer s2) {
    StringBuffer temp = s1;
    s1 = s2;
    s2 = temp;
}


public static void main(String[] args) {
    StringBuffer s1 = new StringBuffer("Hello");
    StringBuffer s2 = new StringBuffer("World");
    swap(s1, s2);
    System.out.println(s1);
    System.out.println(s2);
}
public static void appendWorld(StringBuffer s1) {
    s1.append(" World");
}

public static void main(String[] args) {
    StringBuffer s = new StringBuffer("Hello");
    appendWorld(s);
    System.out.println(s);
}
public static void appendWorld(String s){
    s = s+" World";
}

public static void main(String[] args) {
    String s = new String("Hello");
    appendWorld(s);
    System.out.println(s);
}
class StringWrapper {
    public String value;

    public StringWrapper(String value) {
        this.value = value;
    }
}

public static void appendWorld(StringWrapper s){
    s.value = s.value +" World";
}

public static void main(String[] args) {
    StringWrapper s = new StringWrapper("Hello");
    appendWorld(s);
    System.out.println(s.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. }
Foo f = new Foo("f");
public static void changeReference(Foo a)
changeReference(f);
Foo b = new Foo("b");
public void test() {
    MyClass obj = null;
    init(obj);
    //After calling init method, obj still points to null
    //this is because obj is passed as value and not as reference.
}
private void init(MyClass objVar) {
    objVar = new MyClass();
}
int x = 3;
float y = 101.1f;
boolean amIAwesome = true;
int problems = 99;
String name = "Jay-Z";
JButton[] marxBros = new JButton[3];
marxBros[0] = new JButton("Groucho");
marxBros[1] = new JButton("Zeppo");
marxBros[2] = new JButton("Harpo");
private static void shout(String name){
    System.out.println("There goes " + name + "!");
}

public static void main(String[] args){
    String hisName = "John J. Jingleheimerschmitz";
    String myName = hisName;
    shout(myName);
}
public class PassByValue {
    public static void main(String[] args) {
        Test t = new Test();
        t.name = "initialvalue";
        new PassByValue().changeValue(t);
        System.out.println(t.name);
    }
    
    public void changeValue(Test f) {
        f.name = "changevalue";
    }
}

class Test {
    String name;
}
changevalue
Test t = new Test();
new PassByValue().changeValue(t);
public class PassByValue {
    public static void main(String[] args) {
        Test t = new Test();
        t.name = "initialvalue";
        new PassByValue().changeRefence(t);
        System.out.println(t.name);
    }
    
    public void changeRefence(Test f) {
        f = null;
    }
}

class Test {
    String name;
}
public static 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("X1: " + pnt1.x + " Y1: " +pnt1.y); 
  System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
  System.out.println(" ");
  tricky(pnt1,pnt2);
  System.out.println("X1: " + pnt1.x + " Y1:" + pnt1.y); 
  System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);  
}
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
System.out.println("X1: " + pnt1.x + " Y1: " +pnt1.y); 
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
System.out.println(" ");
X1: 0     Y1: 0
X2: 0     Y2: 0
tricky(pnt1,pnt2);           public void tricky(Point arg1, Point arg2);
 arg1.x = 100;
 arg1.y = 100;
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
X1: 0         Y1: 0
X2: 0         Y2: 0
X1: 100       Y1: 100
X2: 0         Y2: 0
(Name)[Location] -> [Value at the Location]
---------------------
(Ref2Foo)[223]  -> 47
(Foo)[47]       -> 5
public void method (String param) {}
...
String var = new String("ref");
method(var);
method(var.toString());
method(new String("ref"));
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
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]
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]
Account account1 = new Account();
public class Test
{
    public static void reverseArray(int[] array1)
    {
        // ...
    }

    public static void main(String[] args)
    {
        int[] array1 = { 1, 10, -7 };
        int[] array2 = { 5, -190, 0 };

        reverseArray(array1);
    }
}
array1[0] = 5;
array1 = array2;
public class Test
{
    public static int[] reverseArray(int[] array1)
    {
        int[] array2 = { -7, 0, -1 };

        array1[0] = 5; // array a becomes 5, 10, -7

        array1 = array2; /* array1 of reverseArray starts
          pointing to c instead of a (not shown in image below) */
        return array2;
    }

    public static void main(String[] args)
    {
        int[] array1 = { 1, 10, -7 };
        int[] array2 = { 5, -190, 0 };

        array1 = reverseArray(array1); /* array1 of 
         main starts pointing to c instead of a */
    }
}
using namespace std;
#include <iostream>

void change (char *&str){   // the '&' makes this a reference parameter
    str = NULL;
}

int main()
{
    char *str = "not Null";
    change(str);
    cout<<"str is " << str;      // ==>str is <null>
}
public class ValueDemo{

    public void change (String str){
        str = null;
    }

     public static void main(String []args){
        ValueDemo vd = new ValueDemo();
        String str = "not null";
        vd.change(str);
        System.out.println("str is " + str);    // ==> str is not null!!
                                                // Note that if "str" was
                                                // passed-by-reference, it
                                                // WOULD BE NULL after the
                                                // call to change().
     }
}
program passByRefDemo;
type 
   iptr = ^integer;
var
   ptr: iptr;

   procedure setToNil(var ptr : iptr);
   begin
       ptr := nil;
   end;

begin
   new(ptr);
   ptr^ := 10;
   setToNil(ptr);
   if (ptr = nil) then
       writeln('ptr seems to be nil');     { ptr should be nil, so this line will run. }
end.