Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java对象引用和Java方法_Java_Methods_Pass By Reference_Pass By Value_Object Reference - Fatal编程技术网

Java对象引用和Java方法

Java对象引用和Java方法,java,methods,pass-by-reference,pass-by-value,object-reference,Java,Methods,Pass By Reference,Pass By Value,Object Reference,我不明白这是怎么回事 public void addToRule(Rule r) { if (!getRuleList().contains(r)) { getRuleList().addElement(r); } } 如果我运行此代码: obj.addToRule(r); System.out.println(getRuleList().contains(r)); 它打印出true这是怎么发生的 顺便说一句,ruleList是主类的向量成员,不是静态变量(不

我不明白这是怎么回事

public void addToRule(Rule r) {
    if (!getRuleList().contains(r)) {
        getRuleList().addElement(r);
    }
}
如果我运行此代码:

obj.addToRule(r);
System.out.println(getRuleList().contains(r));
它打印出
true
这是怎么发生的

顺便说一句,ruleList是主类的向量成员,不是静态变量(不要认为这很重要,但无论如何都要共享)


好的,有人告诉我这是因为java中的pass-by-reference。我明白了。但是我如何才能获得该对象的副本而不是其引用?

它应该始终打印
true
,因为如果规则不存在,您可以将其添加到规则列表中。发生的情况是:

  • 您告诉对象将规则添加到其规则列表中
  • 对象检查规则是否存在,如果不存在,则添加规则

因此,在执行代码后,它保证包含规则。

我猜
getRuleList()
正在返回对列表(或类似对象)的引用。如果您熟悉C,可以将其视为指针(或者更具体地说,是指针的副本)。当您调用
getRuleList()
时,您正在处理对象的同一底层实例

为了证明,请尝试:
System.out.println(getRuleList()==getRuleList())
=
运算符仅在两个引用指向同一对象时(而不是像
.equals
那样的深度相等)才会进行比较。在使用不同的对象引用调用
setRuleList()
之前,您将看到该语句保持为true


当然,这些假设没有看到您的完整代码。

从您的评论来看,您似乎还没有完全理解Java中值和引用之间的区别。基本上,对象在Java中总是作为引用传递

考虑

class Test {
    private List list = new ArrayList();
    public List getList() {
        return list;
    }
}
getList()
方法将返回对
list
对象的引用。它将返回
列表
对象的副本。像这样做

Test test = new Test();
String s = "ABC";
test.getList().add(s);
System.out.println(test.getList().contains(s));
将返回true,因为第一次调用
getList()
,将返回对列表的引用,并在该引用上调用
add
。第二次调用
getList()
时,它返回对同一列表的引用,而不是它的副本,也不是新列表-同一引用。调用
contains(s)
将返回true,因为它与添加对象
s
的列表相同

然而,考虑一下这一点

Test test1 = new Test();
Test test2 = new Test();
String s = "ABC";
test1.add(s);
System.out.println(test2.getList().contains(s));

这将打印出“false”。为什么?
test1.getList()
返回对test1中列表的引用,而
test2.getList()
返回对test2中列表的引用。这里,
s
被添加到test1:s列表中,因此它不会包含在test2:s列表中。

因此,要回答您的问题,您首先必须知道Java是如何传递变量的

变量有一个值:

int i = 1234;
Person p = new Person("Peter");
现在,变量i正好包含1234,而变量p包含被创建人的内存地址

所以i包含1234,p包含地址(比如a4dfi3)

所以在这个例子中,我们给出了方法anyMethodYouLike变量p。。。等待我们给出了该方法的变量值(a4dfi3)。然后,该方法对该变量调用rename(该变量仍然具有与p相同的地址,因此它修改p指向的同一个人)。 因此,在这个方法之后,p指向的人的名字被打印出来,结果是“荷马”

在本例中,我们仍然将名为“Peter”的人的地址提供给该方法。但这一次,该方法在somePerson中创建了一个新的Person(因此将somePerson中的地址重写为..比如13n37s)。 但是!a4dfi3的人没有改变!打印呼叫仍然输出“Peter”而不是“Walter”

现在,让我们看看这在基本体中的行为:

someMethod(i);
System.out.println(i);
public void someMethod(int someInt) {
   someInt++;
}
因此,i(1234)的值被传递给someInteger。然后someInteger被增加到1235。但i仍然是1234

这就是Java中对象和原语之间的巨大区别

希望我能帮忙,
Ferdi265应该返回true。到底是什么问题?!重新格式化您的代码并使其更易于理解,否则其他人会给您-1;-)我无法理解此行为它没有编译,因为这还不是全部code@Piyush:不应该是
System.out.println(obj.getRuleList().contains(r))?或者getRuleList是静态的?或者测试代码是在obj内部调用的(obj=this)?是的,但我没有调用添加了规则的rulelist的副本。我认为合适的代码应该是:
if(!getRuleList().contains(r)){setRuleList(getRuleList().addElement(r));}
look我不希望它给出false。这是一些我正在查看的预先存在的代码,我无法理解何时可以执行此操作,何时无法执行。不管是什么,如果您不显示整个类,我们都无法帮助我保持有效的答案-我看不出打印
false
的理由。是的,但您不太理解我的要求。最终结果并不重要。我不知道引用是如何传递的。在开始下结论之前,请先看一下标记。当我实现方法
addToRule()
时会发生什么:
public void addToRule(Rule r){if(!getRuleList().contains(r)){Vector list=getRuleList();list.addElement(r);}}
我尝试过,发现它仍然给出true。我该怎么做才能得到一份规则列表而不是一份参考?这要看情况而定。是否只需要包含与原始列表相同的对象引用的列表副本?如果是这样,您可以使用addAll方法()。如果希望它包含列表中所有对象的副本,则必须手动克隆所有对象并将其添加到新列表中。看,哦。。。所以没有简单的方法,嗯?我想这取决于你对“简单”的定义。刚刚得到一份新的名单
anyMethodYouLike(p);
System.out.println(p.getName());
public void anyMethodYouLike(Person somePerson) {
   somePerson.rename("Homer");
}
someOtherMethod(p);
System.out.println(p.getName());
public void someOtherMethod(Person somePerson) {
   somePerson = new Person("Walter");
}
someMethod(i);
System.out.println(i);
public void someMethod(int someInt) {
   someInt++;
}