Ссылка на объект Java и методы Java - PullRequest
0 голосов
/ 02 сентября 2011

Я не могу понять, как это работает

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 ]

1 голос
/ 24 февраля 2013

Итак, чтобы ответить на ваши вопросы, вы сначала должны знать, как Java передает переменные.

переменная имеет значение:

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

Теперь переменная i содержит ровно 1234,в то время как переменная p содержит адрес памяти созданного персонажа.

, поэтому в i содержится 1234, а p содержит адрес (скажем, a4dfi3).

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

, поэтому в этом примере мы даемМетод anyMethodYouLike Переменная p ... подождите!мы даем методу значение переменной (a4dfi3).Затем метод вызывает метод переименования для этой переменной (которая по-прежнему имеет тот же адрес, что и p, поэтому он изменяет тот же объект Person, на который указывает p).Итак, после того, как Метод, Имя Человека, на которое указывает р, печатается, в результате получается «Гомер».

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

В ЭТОМ примере мы все еще даем адрес нашего Человека, называемого «Петр»,метод.Но на этот раз Метод создает нового Person в somePerson (поэтому переопределяет адрес в somePerson на ... скажем, 13n37s. НО! Человек в a4dfi3 не изменился! При вызове print по-прежнему выводится "Peter", а не "Walter".

Теперь давайте посмотрим, как это происходит с примитивами:

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

Итак, значение i (1234) передается someInteger. Затем someInteger увеличивается до 1235. Но япо-прежнему 1234.

Это большая разница между объектами и примитивами в Java.

Надеюсь, я смогу помочь, Ferdi265

1 голос
/ 02 сентября 2011

Я предполагаю, getRuleList() возвращает ссылку в Список (или что-то подобное).Думайте об этом как о указателе (или, точнее, о копии указателя), если вы знакомы с C. Вы работаете над тем же базовым экземпляром объекта, когда вызываете getRuleList().

Для доказательства попробуйте: System.out.println(getRuleList() == getRuleList());Оператор == будет сравниваться только в том случае, если две ссылки указывают на один и тот же объект (а не на глубину, равную .equals).Вы увидите, что до тех пор, пока вы не вызовете setRuleList() с другим объектом ссылка , это утверждение верно.

Эти предположения, конечно, не видят ваш полный код.

0 голосов
/ 02 сентября 2011

Из ваших комментариев видно, что вы не до конца поняли, в чем разница между значением и ссылкой в ​​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));

Вернет true с момента первого вызова getList(), возвращается ссылка на список, по которому вызывается 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));

Это выведет "false". Зачем? test1.getList() возвращает ссылку на список внутри test1 , а test2.getList() возвращает ссылку на список внутри test2 . Здесь s было добавлено в список test1: s, поэтому оно не будет содержаться в списке test2: s.

0 голосов
/ 02 сентября 2011

Всегда должно печататься true, потому что вы добавляете правило в список правил, если его там нет.Происходит следующее:

  • вы указываете объекту добавить добавить правило в список правил
  • объекты проверяют, существует ли правило, а если нет, добавляет его

Таким образом, гарантированно будет содержаться правило после выполнения кода.

...