[英]Parameters passing in Java
I have a Long object in a class, I give it a value and then I pass it to another class' constructor, where it is changed. 我在一个类中有一个Long对象,给它一个值,然后将其传递给另一个类的构造函数,在该构造函数中对其进行更改。 Why are the changes NOT visible in the first object?
为什么更改在第一个对象中不可见?
The code: 编码:
public class ClassA {
private Long t;
public ClassA() {
t = new Long(10);
System.out.println(t); // prints 10
new ClassB(t); // it is modified (see ClassB)
System.out.println(t); // prints 10 again
}
public static void main(String[] args) {
new ClassA();
}
}
class ClassB {
private Long p;
public ClassB(Long p) {
this.p = p;
this.p = this.p + 1;
System.out.println(this.p); // prints 11
}
}
The output is: 10 11 10 The Long variable is initialized in ClassA. 输出为:10 11 10 Long变量在ClassA中初始化。 Then I pass it to ClassB, modify it and clearly the changes are not visible in the first class.
然后,将其传递给ClassB,对其进行修改,并且显然在第一堂课中看不到更改。 Why?
为什么?
It is because the Long
class is immutable; 这是因为
Long
类是不可变的。 once an instance is created, it can never change. 创建实例后,就永远无法更改。
In this line: 在这一行:
this.p = this.p + 1;
what you are doing is create a new Long
object. 您正在做的是创建一个新的
Long
对象。 Other examples of immutable classes include all "wrapper" classes for primitive numeric types ( Byte
, Short
etc) and String
. 不可变类的其他示例包括原始数字类型(
Byte
, Short
等)和String
所有“包装”类。
What doesn't help is that it makes the +
operator unintuitive; 无济于事的是,它使
+
运算符不直观。 what really does not help is that the language allows +
on all of these immutable classes. 真正没有帮助的是,该语言允许在所有这些不可变的类上使用
+
。
What happens in the above line could be written as (although it happens differently in the bytecode, I suspect): 上一行发生的情况可以写成(尽管我怀疑字节码中发生的情况有所不同):
long tmp = this.p.longValue();
tmp += 1;
this.p = new Long(tmp);
You can also verify immutability by marking your p
as final
in class B
, which means the reference p
can never change; 您还可以通过在
B
类中将p
标记为final
来验证不变性,这意味着引用 p
永远不会改变; this.p = this.p + 1
will raise a compile error since you attempt to modify reference p
. 由于您尝试修改引用
p
this.p = this.p + 1
会引发编译错误。
this line this.p = this.p + 1;
这行
this.p = this.p + 1;
does not modify p, it creates a new Long
from adding the two values p
and 1
and then sets this.p
to be a reference to this new Long
. 不会修改p,而是通过将两个值
p
和1
相加来创建一个新的Long
,然后将this.p
设置为对此新Long
的引用。 Objects of the class Long
do not have mutator methods so they can never change (within Class B this.p
was not changed, this.p
became a reference to a new Long) 类的对象
Long
没有突变的方法,使他们能够永远不会改变(B类中this.p
没有改变, this.p
成为了一个新的龙的引用)
So the behaviour is actually 所以行为实际上是
this.p=p;
Long newLong=this.p + 1;
this.p=newLong;
What you're imagining is 你在想的是
this.p=p
this.p.imaginaryAddLocal(1);
this would effect the original p, but of course this method imaginaryAllLocal
doesn't exist because objects of the class Long are immutable 这会影响原始的p,但是当然不存在这种方法
imaginaryAllLocal
,因为Long类的对象是不可变的
To begin with, Long
is immutable. 首先,
Long
是不可变的。 It means you cannot change the value that you set in the constructor (note the absence of set
methods). 这意味着您无法更改在构造函数中设置的值(请注意,没有
set
方法)。
When you do 当你做
this.p = this.p + 1;
Java does. Java。
1) Autoconvert this.p
to its long value (primitive) 1)自动将
this.p
转换为其长值(原始)
2) Arithmetic operation 2)算术运算
3) Autoconvert the result back to a new, different Long and assign the reference to this.p
3)将结果自动转换回新的不同的Long并将引用分配给
this.p
t
continues pointing, all the time, to the original Long
object. t
一直一直指向原始的Long
对象。
In Java, you modify objects through its attributes (not adviceable, you should make them private
) or its methods. 在Java中,您可以通过对象的属性(不建议使用,应将它们设置为
private
)或其方法来修改对象。 A +
(or other operator) will never change an object state (although it may create a new one, in the only case of myString1 + myString2
) +
(或其他运算符)将永远不会更改对象状态(尽管可能会创建一个新的对象状态,仅在myString1 + myString2
情况下)
1- You are just modifying the p member of class B 1-您只是在修改B类的p成员
2- Everything is passed by value (and not by reference) in Java 2-Java中的所有内容都按值(而不是引用)传递
The Long
class is immutable, so you can not pass back the value by modifying it in the called function. Long
类是不可变的,因此您不能通过在调用的函数中对其进行修改来传回该值。 In your ClassB
a copy is created and the original value is never changed. 在您的
ClassB
,将创建一个副本,并且原始值永远不会更改。
If you want the caller to see the changed value, you must pass it back as return value. 如果希望呼叫者看到更改的值,则必须将其作为返回值传递回去。
The same is true for the other primitive wrappers and String. 其他原始包装器和String也是如此。
Because Java uses pass-by-reference. 因为Java使用传递引用。 This means that it passes a copy of the variable, and not a reference to the "original" one.
这意味着它将传递变量的副本 ,而不是对“原始”变量的引用。
Eg in C++, you can do this: 例如,在C ++中,您可以执行以下操作:
void change_var(int &x)
{
x = 2;
}
int x = 10;
change_var(x);
std::cout << x << std::endl;
This would print 2
, since the reference to the variable x
is being passed, and not a copy. 由于将传递对变量
x
的引用,而不是副本,因此将打印2
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.