java中的按值传递和按引用传递

java中的按值传递和按引用传递,java,oop,core,Java,Oop,Core,我正在阅读关于java中按值传递和按引用传递的文章,我得到了很多文章,其中一些文章说java只遵循“按值传递”,一些文章说原语和对象之间存在一些差异。因此我编写了以下示例代码。 并把输出也放进去。 请评论并分享答案 我检查了Int、String、StringBuffer和Employee类,现在它只作为Employee类的passby引用 package test; class Emp { public String name=""; public int age=0;

我正在阅读关于java中按值传递和按引用传递的文章,我得到了很多文章,其中一些文章说java只遵循“按值传递”,一些文章说原语和对象之间存在一些差异。因此我编写了以下示例代码。 并把输出也放进去。 请评论并分享答案

我检查了Int、String、StringBuffer和Employee类,现在它只作为Employee类的passby引用

package test;
class Emp {
    public String name="";
    public int age=0;

    public Emp(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String toString() {
        return "Name: "+ this.name + "....Age: "+ this.age;

    }
}
public class Class1 {
    public Class1() {
        super();
    }

    public void doChange(int i) {
        i = i +10;
        System.out.println("Value of Integer in Method:>"+ i);
    }

    public void doChange(Emp i) {
        i.age=29;
        i.name="rishu";
        System.out.println("Value of Employee In Method "+i.toString());
    }

    public void doChange(String i) {
        i = i + " Hello";
        System.out.println("value of i->"+ i);
    }


    public static void main(String[] args) {
        int i =10;
        String str="XXX";
        Class1 c= new Class1();
        StringBuffer sb= new StringBuffer();
        Emp e= new Emp("abhi",28);       

        sb.append("ABC ");
        System.out.println("");
        System.out.println("Value of Integer before Method:->"+ i);
        c.doChange(i);
        System.out.println("Value of Integer after Method:->"+ i);
        System.out.println("");
        System.out.println("Value of String before Method:->"+ str);
        c.doChange(str);
        System.out.println("Value of Integer after Method:->"+ str);
        System.out.println("");
        System.out.println("Value of StringBuffer before Method:->"+ sb);
        c.doChange(sb.toString());
        System.out.println("Value of StringBuffer after Method:->"+ sb);
        System.out.println("");

        System.out.println("Value of Employee before Method:->"+ e.toString());
        c.doChange(e);
        System.out.println("Value of Employee after Method:->"+ e.toString());
    }
}
输出:

Value of Integer before Method:->10
Value of Integer in Method:>20
Value of Integer after Method:->10

Value of String before Method:->XXX
value of i->XXX Hello
Value of Integer after Method:->XXX

Value of StringBuffer before Method:->ABC 
value of i->ABC  Hello
Value of StringBuffer after Method:->ABC 

Value of Employee before Method:->Name: abhi....Age: 28
Value of Employee In Method Name: rishu....Age: 29
Value of Employee after Method:->Name: rishu....Age: 29

Java中没有按引用传递,只有按值传递

当此方法退出时,employee将不是chin boon,而是您在输入此方法之前将其设置为的其他内容

public void doChange(Emp i) {
    i = new Emp("chin boon", 42);
}
当此方法退出时,employee的名称为chin boon

public void doChange(Emp i) {
    i.setName("chin boon");
}

Java只是按值传递

但是,对于对象,按值传递的是对对象的引用。不,这与按引用传递不同。区别在于:

如果您这样做:

public void doChange(Emp i) {
    i = new Emp("changed!", 42);
}

它在方法之外绝对没有效果-因为引用
i
是在方法之外使用的引用的副本。但是,它引用同一个对象,因此如果使用引用更改对象的字段,这些更改在方法之外是可见的。

Java使用传递值将参数传递给方法即,方法调用的每个指定参数的值的
副本作为其参数传递给方法

请非常清楚地注意,许多人混淆了“参考”关于Java对对象的引用和按引用传递调用语义的术语。事实上,在处理Java对对象的引用时,引用值的副本就是传递给方法的内容——它是按值传递的。例如,这就是为什么不能从被调用的方法内部改变对对象的(原始的、调用方的)引用

例如:

Dog aDog = new Dog("Max");
您正在定义指向Dog aDog对象的指针,而不是Dog对象本身

public void foo(Dog d) {
   d = new Dog("Bingo");
}
传入的变量未修改!在打电话给foo之后,aDog仍然指向“Max”狗。将d的值传递给foo,指针的值类似于内存地址

方法之前的整数值:->10方法中的整数值:->20方法之后的整数值:->10

这并不奇怪。将值10传递给该方法,该值将递增并正确显示。从方法调用返回后,
i
变量保持不变

方法之前的字符串值:->i的XXX值->方法之后的整数的XXX值:->XXX

字符串是不可变的类,因此无法更改它。您只能重新分配值,就像您在示例中所做的那样。这里的诀窍是要理解,您将收到一个复制的引用值,该值将导致object
XXX
。现在,您正在创建新对象
i+“Hello”
并覆盖以前的引用
i
。因此,对象
XXX
不会更改,但是在方法中您没有打印它-您正在打印在方法中创建的对象

方法之前StringBuffer的值:->i的ABC值->方法之后StringBuffer的ABC Hello值:->ABC

这与上面代码中的情况相同,因为
toString()
生成一个新的
String
对象

最后:

方法之前的员工值:->姓名:abhi….年龄:28方法名称中的员工值:rishu….年龄:29方法之后的员工值:->姓名:rishu….年龄:29

这是传递价值的完美展示 您正在创建对象
Employee
,但正在将对此对象的引用作为方法参数传递。现在,终生记住这一点,此引用已被复制,因此您将收到一份可供您在方法内部使用的引用副本这就是为什么JAVA总是按副本传递的原因。 但是,此复制的引用仍然指向您先前创建的同一对象
Employee
。因此,如果要使用该引用修改它所指向的对象,则需要修改原始的
Employee
。这就是为什么您可以在输出中看到更改效果

Bruce Eckel
提供了一个Java中引用和对象的好例子。把物体想象成电视,把参照物想象成遥控器。如果将对其他方法的引用作为参数传递,则此方法中将复制一个遥控器。如果按方法中的“关闭”按钮,即使未使用原遥控器,电视仍会关闭;)

我们可以在java中同时执行“按值传递”和“按引用传递”,这里是这两种方法的示例

传递值示例

class PassByValue{
String name="java";
void display(String name)
{
    name="Java Programming";
}
public static void main(String arg[])
{
    PassByValue p=new PassByValue();
    System.out.println("Before changes : "+p.name);
    p.display("C++");
    System.out.println("After changes : "+p.name);
}}
class PassByReference{
String name="Java";
void display(PassByReference p)
{
    name="Java Programming";
}
public static void main(String arg[])
{
    PassByReference p=new PassByReference();
    System.out.println("Before changes : "+p.name);
    p.display(p);
    System.out.println("After changes : "+p.name);
}}
通过参考示例传递

class PassByValue{
String name="java";
void display(String name)
{
    name="Java Programming";
}
public static void main(String arg[])
{
    PassByValue p=new PassByValue();
    System.out.println("Before changes : "+p.name);
    p.display("C++");
    System.out.println("After changes : "+p.name);
}}
class PassByReference{
String name="Java";
void display(PassByReference p)
{
    name="Java Programming";
}
public static void main(String arg[])
{
    PassByReference p=new PassByReference();
    System.out.println("Before changes : "+p.name);
    p.display(p);
    System.out.println("After changes : "+p.name);
}}

通过单击此处,您可以在java中检查返回值返回对象

请参见:
i.name=“rishu”
i=rishu
(或
i=new Emp(“rishu”,…)
)之间有很大区别。第一个是更改保存在
i
中的对象,第二个是更改
i
本身。非常感谢,请帮助我了解Employee类是如何这样工作的。我在方法中修改为修改String和StringBuffer。@Abhishek:String对象的内容不能更改-您的doChange()方法创建一个新对象并将其指定给引用的副本。对于StringBuffer,要产生效果是不可能的,因为sb.toString()创建StringBuffer内容的副本,然后创建传递给方法的引用ot的副本。