简体   繁体   English

Java中传递的参数

[英]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 . 不可变类的其他示例包括原始数字类型( ByteShort等)和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,而是通过将两个值p1相加来创建一个新的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM