java中的按值传递和按引用传递
我正在阅读关于java中按值传递和按引用传递的文章,我得到了很多文章,其中一些文章说java只遵循“按值传递”,一些文章说原语和对象之间存在一些差异。因此我编写了以下示例代码。 并把输出也放进去。 请评论并分享答案 我检查了Int、String、StringBuffer和Employee类,现在它只作为Employee类的passby引用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;
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
字符串是不可变的类,因此无法更改它。您只能重新分配值,就像您在示例中所做的那样。这里的诀窍是要理解,您将收到一个复制的引用值,该值将导致objectXXX
。现在,您正在创建新对象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的副本。