首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以将对象作为函数参数传递并在函数中重新分配,从而在java中将其值修改为函数范围之外的值?

是否可以将对象作为函数参数传递并在函数中重新分配,从而在java中将其值修改为函数范围之外的值?
EN

Stack Overflow用户
提问于 2022-01-17 03:53:04
回答 2查看 1.1K关注 0票数 0

我对Java中的逐值机制感到困惑,尽管我读过一些关于它的问题,比如thisthis

我认为原语类型是通过函数参数中的值传递的,所以即使它在函数作用域中被更改,它也不会更改它的值。

代码语言:javascript
复制
public class A {
    void function(int i) {
        i = 3;
    }

    public static void main(String[] args) {
        int i = 2;
        function(i);
        System.out.println(i);  // variable `i` won't change
    }
}

但是类对象是通过函数参数中引用的值传递的,因此如果函数范围中的引用被更改,它将更改其值。

代码语言:javascript
复制
public class Obj{
    public double calPrice;
    public boolean isTop;
    public boolean isCate;
    public List<Integer> cList;
    public RPCRecord(double c, boolean iT, boolean iC, List<Integer> cL) {
        calPrice = c;
        isTop = iT;
        isCate = iC;
        cList = cL;
    }
}

void f2(Obj o) {
    List<Integer> l1 = new ArrayList<Integer>(){{
                        add(1);
                        add(2);
                        add(3);
                          }};
    Obj o2 = new Obj(10.0, true, false, l1);
    o = o2;
}

void f3(Obj obj) {
    obj.calPrice = 123123.1;
    obj.isTop = false;
    obj.add(10);
}

public class A {
    public static void main(String[] args) {
        Obj ojb = new Obj();
        f2(ojb);
        System.out.println(ojb);  // Object `obj` will change
        f3(ojb);
        System.out.println(ojb);  // Object `obj` will change
    }
}

请原谅我对Java参数机制不够熟悉。

我是这么想的对吗?

EN

回答 2

Stack Overflow用户

发布于 2022-01-17 05:06:18

我认为这对于Java中的逐值传递来说是一种常见的混淆。

如果您想从规则的角度来考虑它:如果将对象(引用)传递给方法,则不能更改传入的对象。换句话说,您不能更改对另一个对象的引用。

您能够做的是更改对象中的内容--上面的f3方法应该可以更改传递给它的对象中的内容。

但是,您不能--就像您在f2中试图做的那样--将传入的对象(A类中的ojb)更改为另一个对象。若要从方法返回对象,必须在方法的return语句中返回该对象,或者必须是另一个对象中的字段,以便在另一个对象中更改该对象。

现在,如果您想要更低层次的解释,而不是规则:

当您将对象变量名称作为参数放入Java中的方法时,您将传递一个指向该对象的“指针”。您可以将它看作是由内存中的地址表示的对象,并且传递一个保存该地址的变量。您可以将保存对象地址的变量看作是通过值传递的,即使是通过引用传递对象。

该方法将参数作为一种特殊的变量来获取,并可以使用参数变量引用该对象。该方法可以更改变量;它不能为调用方更改它。

从上面采取你的方法:

代码语言:javascript
复制
void f2(Obj o) {
    List<Integer> l1 = new ArrayList<Integer>(){{
                        add(1);
                        add(2);
                        add(3);
                          }};
    Obj o2 = new Obj(10.0, true, false, l1);
    o = o2;
}

调用者传入包含指向对象的指针的参数“变量”;f2方法调用该参数变量of2可以更改参数变量的值。但是,该地址上的任何对象仍然驻留在该地址上,而持有该地址的调用者中的任何变量仍然持有该地址。

查看它的另一种方法是:假设调用方将一个名为george的变量传递给您的f2方法:

代码语言:javascript
复制
SomeObject george = new SomeObject();
f2(george);

假设george的地址是1234。然后,我们可以将of2中想象为持有1234,即george的地址。f2Obj o2 = new Obj(10.0, true, false, l1);创建一个新对象,假设o2位于地址5678。o = o2语句在您的f2中所做的是将5678赋值给o,替换以前存在的1234。这不会影响调用者;george仍然在1234。f2更改了一个保存george地址的变量,但调用方无法知道这一点。

票数 2
EN

Stack Overflow用户

发布于 2022-01-17 04:58:49

在调用具有基元类型的方法时,传递(字节、短、字符、int、长、浮点、双、布尔值)值,其中包含对象-引用。

换句话说,不可能在调用方法时将原始变量(如int )作为参数传递来更改它的初始值。但是它对一个对象是可行的,但只有在它是一个可变对象的情况下才是可行的。例如,您可以使用自定义类Obj的实例或实例,但不能更改BigInteger或String,这些类设计为不可变。

https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70736350

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档