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++;
}