Java对象参考和Java方法

时间:2022-06-08 16:58:34

I am unable to understand how this works

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

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

If I run this code:

如果我运行此代码:

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

it prints out true how can this happen?

它打印出真的如何发生这种情况?

btw ruleList is a vector member of the main class and is not a static variable(don't think this matters but sharing anyway).

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

OK people have told me that this works because of the pass by reference in java. I get it. but what can i do to get a copy of that object instead of its reference?

好的人告诉我,这是有效的,因为java中的引用传递。我知道了。但我该怎么做才能得到该对象的副本而不是它的引用?

4 个解决方案

#1


0  

From your comments it looks like you have not completely understood what the difference is between a value and a reference in Java. Basically, objects are always passed around as references in Java.

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

Consider

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

The getList() method will return a reference to the list object. It will not return a copy of the list object. Doing something like

getList()方法将返回对列表对象的引用。它不会返回列表对象的副本。做点什么

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

Will return true since the first time getList() is called, a referece to the list is returned, on which add(s) is invoked. The second time getList() is called, it returns a reference to the same list, not a copy of it, not a new list - the same reference. Calling contains(s) will return true since it the same list onto which the object s was added.

从第一次调用getList()开始返回true,返回对列表的引用,在其上调用add(s)。第二次调用getList()时,它返回对同一列表的引用,而不是它的副本,而不是新列表 - 相同的引用。调用contains(s)将返回true,因为它与添加了对象的列表相同。

Consider this, however.

但是请考虑一下。

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

This will print out "false". Why? test1.getList() returns a reference to the list inside test1 and test2.getList() returns a reference to the list inside test2. Here, s was added to test1:s list, so it will not be contained inside test2:s list.

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

#2


1  

I'm guessing getRuleList() is returning a reference to a List (or something similar). Think of it as a pointer (or more specifically, a copy of a pointer) if you're familiar with C. You're working on the same underlying instance of the object when you call getRuleList().

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

For proof, try: System.out.println(getRuleList() == getRuleList()); The == operator will only compare if the two references are pointing to the same object (not a deep equal like .equals). You'll see that until you call setRuleList() with a different object reference that the statement holds true.

为了证明,请尝试:System.out.println(getRuleList()== getRuleList()); ==运算符只会比较两个引用是否指向同一个对象(不是像.equals那样的深度)。您将看到,直到您使用不同的对象引用调用setRuleList(),该语句为true。

These assumptions are of course without seeing your full code.

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

#3


1  

So, to answer your questions you have to at first know how Java passes Variables.

因此,要回答您的问题,首先要了解Java如何通过变量。

a Variable has a value:

变量有一个值:

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

Now, the Variable i contains exactly 1234, while the Variable p contains the Memory Adress of the created Person.

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

so i contains 1234 and p contains the adress (let's say a4dfi3).

所以我包含1234而p包含地址(让我们说a4dfi3)。

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

so in this example, we give the Method anyMethodYouLike the Variable p... wait! we give the Method the value of the Variable (a4dfi3). The Method then calls rename on this Variable (which still has the same adress as p has, hence it modifies the same Person that p points to). So, after the Method, the Name of the Person p points to, gets printed, which results in "Homer".

所以在这个例子中,我们给方法anyMethodYouLike变量p ...等等!我们给Method提供变量(a4dfi3)的值。然后,Method调用此变量上的重命名(它仍具有与p相同的地址,因此它会修改p指向的同一个Person)。因此,在方法之后,人物的名称p指向,被打印,这导致“荷马”。

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

In THIS example we still give the adress of our Person called "Peter" to the Method. But this time, the Method creates a new Person in somePerson (therefore overriding the adress in somePerson to.. let's say 13n37s. BUT! the Person at a4dfi3 wasn't changed! The print call still outputs "Peter" and not "Walter".

在这个例子中,我们仍然将我们的Person的地址称为“Peter”。但是这一次,方法在somePerson中创建了一个新的Person(因此覆盖了somePerson中的地址......让我们说13n37s。但是!a4dfi3的人没有改变!打印调用仍然输出“Peter”而不是“Walter” 。

Now, let's see how this behaves with primitives:

现在,让我们看看这与原语的行为:

someMethod(i);
System.out.println(i);
public void someMethod(int someInt) {
   someInt++;
}

So, the Value of i (1234) gets passed to someInteger. Then someInteger gets incremented to 1235. But i is still 1234.

因此,i(1234)的值被传递给someInteger。然后someInteger增加到1235.但我仍然是1234。

This is the big difference between Objects and primitives in Java.

这是Java中对象和原语之间的巨大差异。

Hope I could help, Ferdi265

希望我能帮忙,Ferdi265

#4


0  

It should always print true, because you add the rule to the rule list in case it is not there. What happens is:

它应该始终打印为true,因为您将规则添加到规则列表中,以防它不存在。会发生什么:

  • you tell the object to add add a rule to its rule list
  • 您告诉对象添加规则到其规则列表

  • the objects checks if the rule exists, and if it doesn't, adds it
  • 对象检查规则是否存在,如果不存在,则添加它

So it is guaranteed to contain the rule after the code is executed.

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

#1


0  

From your comments it looks like you have not completely understood what the difference is between a value and a reference in Java. Basically, objects are always passed around as references in Java.

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

Consider

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

The getList() method will return a reference to the list object. It will not return a copy of the list object. Doing something like

getList()方法将返回对列表对象的引用。它不会返回列表对象的副本。做点什么

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

Will return true since the first time getList() is called, a referece to the list is returned, on which add(s) is invoked. The second time getList() is called, it returns a reference to the same list, not a copy of it, not a new list - the same reference. Calling contains(s) will return true since it the same list onto which the object s was added.

从第一次调用getList()开始返回true,返回对列表的引用,在其上调用add(s)。第二次调用getList()时,它返回对同一列表的引用,而不是它的副本,而不是新列表 - 相同的引用。调用contains(s)将返回true,因为它与添加了对象的列表相同。

Consider this, however.

但是请考虑一下。

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

This will print out "false". Why? test1.getList() returns a reference to the list inside test1 and test2.getList() returns a reference to the list inside test2. Here, s was added to test1:s list, so it will not be contained inside test2:s list.

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

#2


1  

I'm guessing getRuleList() is returning a reference to a List (or something similar). Think of it as a pointer (or more specifically, a copy of a pointer) if you're familiar with C. You're working on the same underlying instance of the object when you call getRuleList().

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

For proof, try: System.out.println(getRuleList() == getRuleList()); The == operator will only compare if the two references are pointing to the same object (not a deep equal like .equals). You'll see that until you call setRuleList() with a different object reference that the statement holds true.

为了证明,请尝试:System.out.println(getRuleList()== getRuleList()); ==运算符只会比较两个引用是否指向同一个对象(不是像.equals那样的深度)。您将看到,直到您使用不同的对象引用调用setRuleList(),该语句为true。

These assumptions are of course without seeing your full code.

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

#3


1  

So, to answer your questions you have to at first know how Java passes Variables.

因此,要回答您的问题,首先要了解Java如何通过变量。

a Variable has a value:

变量有一个值:

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

Now, the Variable i contains exactly 1234, while the Variable p contains the Memory Adress of the created Person.

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

so i contains 1234 and p contains the adress (let's say a4dfi3).

所以我包含1234而p包含地址(让我们说a4dfi3)。

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

so in this example, we give the Method anyMethodYouLike the Variable p... wait! we give the Method the value of the Variable (a4dfi3). The Method then calls rename on this Variable (which still has the same adress as p has, hence it modifies the same Person that p points to). So, after the Method, the Name of the Person p points to, gets printed, which results in "Homer".

所以在这个例子中,我们给方法anyMethodYouLike变量p ...等等!我们给Method提供变量(a4dfi3)的值。然后,Method调用此变量上的重命名(它仍具有与p相同的地址,因此它会修改p指向的同一个Person)。因此,在方法之后,人物的名称p指向,被打印,这导致“荷马”。

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

In THIS example we still give the adress of our Person called "Peter" to the Method. But this time, the Method creates a new Person in somePerson (therefore overriding the adress in somePerson to.. let's say 13n37s. BUT! the Person at a4dfi3 wasn't changed! The print call still outputs "Peter" and not "Walter".

在这个例子中,我们仍然将我们的Person的地址称为“Peter”。但是这一次,方法在somePerson中创建了一个新的Person(因此覆盖了somePerson中的地址......让我们说13n37s。但是!a4dfi3的人没有改变!打印调用仍然输出“Peter”而不是“Walter” 。

Now, let's see how this behaves with primitives:

现在,让我们看看这与原语的行为:

someMethod(i);
System.out.println(i);
public void someMethod(int someInt) {
   someInt++;
}

So, the Value of i (1234) gets passed to someInteger. Then someInteger gets incremented to 1235. But i is still 1234.

因此,i(1234)的值被传递给someInteger。然后someInteger增加到1235.但我仍然是1234。

This is the big difference between Objects and primitives in Java.

这是Java中对象和原语之间的巨大差异。

Hope I could help, Ferdi265

希望我能帮忙,Ferdi265

#4


0  

It should always print true, because you add the rule to the rule list in case it is not there. What happens is:

它应该始终打印为true,因为您将规则添加到规则列表中,以防它不存在。会发生什么:

  • you tell the object to add add a rule to its rule list
  • 您告诉对象添加规则到其规则列表

  • the objects checks if the rule exists, and if it doesn't, adds it
  • 对象检查规则是否存在,如果不存在,则添加它

So it is guaranteed to contain the rule after the code is executed.

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