-1

我无法理解这是如何工作的

public void addToRule(Rule r) {
    if (!getRuleList().contains(r)) {
        getRuleList().addElement(r);
    }
}

如果我运行此代码:

obj.addToRule(r);
System.out.println(getRuleList().contains(r));

它打印出true这怎么会发生?

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

import java.util.Vector;


public class RuleEngine{

    private Vector ruleList = new Vector();

    public Vector getRuleList(){
        return ruleList;
    }

    public void addToRule(Rule r){
        if(!getRuleList().contains(r))
            getRuleList().addElement(r);
    }

    public static void main(String args[]){
        RuleEngine re = new RuleEngine();
        Rule r = new Rule("Rule1");
        re.addToRule(r);
        System.out.println(re.getRuleList().contains(r));
    }
}

class Rule{
    public String name = "";
    public Rule(String nam){
        this.name=nam;
    }
}

好的人们告诉我,这是因为 java 中的引用传递。我得到它。但是我能做些什么来获取该对象的副本而不是它的引用?

4

4 回答 4

1

我猜getRuleList()是返回对 List 的引用(或类似的东西)。如果您熟悉 C,可以将其视为指针(或更具体地说,指针的副本)。当您调用getRuleList().

为了证明,请尝试System.out.println(getRuleList() == getRuleList()):运算符仅在==两个引用指向同一个对象时才进行比较(不是深度相等.equals)。您将看到这一点,直到您使用该语句成立setRuleList()的不同对象引用进行调用。

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

于 2011-09-02T11:53:30.447 回答
1

因此,要回答您的问题,您首先必须了解 Java 如何传​​递变量。

一个变量有一个值:

int i = 1234;
Person p = new Person("Peter");

现在,变量 i 正好包含 1234,而变量 p 包含创建的 Person 的内存地址。

所以 i 包含 1234 而 p 包含地址(比方说 a4dfi3)。

anyMethodYouLike(p);
System.out.println(p.getName());
public void anyMethodYouLike(Person somePerson) {
   somePerson.rename("Homer");
}

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

someOtherMethod(p);
System.out.println(p.getName());
public void someOtherMethod(Person somePerson) {
   somePerson = new Person("Walter");
}

在此示例中,我们仍然将名为“Peter”的 Person 的地址提供给 Method。但是这一次,该方法在 somePerson 中创建了一个新的人(因此将 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

于 2013-02-24T10:46:35.877 回答
0

它应该总是 print true,因为您将规则添加到规则列表以防万一它不存在。会发生什么:

  • 你告诉对象添加一个规则到它的规则列表
  • 对象检查规则是否存在,如果不存在,则添加它

所以保证在代码执行后包含规则。

于 2011-09-02T11:43:24.170 回答
0

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

考虑

class Test {
    private List list = new ArrayList();
    public List getList() {
        return list;
    }
}

getList()方法将返回对该对象的引用。list不会返回对象的副本list。做类似的事情

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

自第一次getList()调用后将返回 true,返回对列表的引用,并在其add(s)上调用。第二次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));

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

于 2011-09-02T12:05:34.617 回答