Проблема с передачей ссылок на объекты в Java - PullRequest
1 голос
/ 25 июня 2010

Я пишу кое-что на Java, и в последнее время у меня возникли проблемы. Вкратце, мне нужно сравнить объект, который я создал, с другим экземпляром этого самого класса, который я инстанцировал ранее, с другими данными.

выглядит так:

a newA = null;
a oldA = null;

while(someBreakCondition) {
    newA = new a();

    newA.x = getSomeValue();

    // now i want to compare the two objects
    if(oldA != null) {
        if(newA.time != oldA.time) {
            // ...
        }
    }

    // now my newA gets to be my oldA, since in the next iteration, a new newA is created
    oldA = newA;
}

с классом А:

class a {
    public long time;
    public int x;

    public a() {
        time = System.currentTimeMillis;
    }
}

проблема в том, что я обнаружил, что значения из newA всегда равны значениям из oldA. так что я думаю, что что-то пошло не так с передачей ссылок на объекты в последней строке цикла ... я думал, что Java всегда передает ссылки на объекты, если явно не вызывается copy ()?

если это имеет значение: этот код работает на Android - не знаю, если dalvik vm портится с этим ...

Ответы [ 5 ]

7 голосов
/ 25 июня 2010

Я думаю, у вас, вероятно, есть два разных объекта, но они оба имеют одинаковое значение для time. Текущий миллис не совсем способен различать два объекта, построенных в быстрой последовательности, если только ваш внутренний цикл не работает долго. Даже у процессора Mhz итерации измеряются в микросекундах, а не миллисекундах.

4 голосов
/ 25 июня 2010

Существует вероятность, что два объекта a создаются в одну и ту же миллисекунду, поэтому поля 'времени' равны.

Я не уверен в ваших требованиях к сравнению, но, возможно, вам следуетпереписать equals:

public class A {
  private long time;
  private int x;

  public A() {
    time = System.currentTimeInMillis();
  }

  public void setX(int x) {
    this.x = x;
  }

  public int getX() {
    return x;
  }


  public boolean equals(Object other) {
    if (!(other instanceof A)) return false;

    // two A instances are equal if they are created 
    // within the same millisecond
    return ((A) other).time == time);
  }
}

, затем просто сделать

if (!(newA.equals(oldA)) {
  // ...
}

Для будущего кодирования - пожалуйста, назовите классы так, чтобы они начинались с заглавной буквы (соглашения по кодированию)

1 голос
/ 25 июня 2010

Под словом "я в конечном итоге" вы подразумеваете "после того, как я выйду из цикла while"?

Потому что в этом случае проблема проста: в последней итерации циклаoldA перезаписывается последним значением newA, в то время как newA никогда не перезаписывается новым экземпляром.

Итак, когда вы выходите из цикла while, newA и oldA всегда равны - следствиепоследнего шага атрибуции последнего выполнения цикла.

1 голос
/ 25 июня 2010

Я не знаю, как поместить код в комментарии, поэтому я добавлю это как ответ на неправильный ответ Аймена:)

Попробуйте, и вы точно увидите, что происходит :)

public class Test {
  private int value;
  public Test(){

  }

  public int getValue() {
    return value;
  }

  public void setValue(int value) {
    this.value = value;
  }


}

public class Main {

    public static void main(String[] args) {
      Test oldA = null;
      Test newA = null;


      newA = new Test();
      newA.setValue(1);

      oldA = newA;

      // both variables references the same object: output: 1 - 1
      System.out.println("newA: " + newA.getValue());
      System.out.println("oldA: " + oldA.getValue());

      newA = new Test();
      newA.setValue(2);

      // now we have different objects: output: 2 - 1
      System.out.println("newA: " + newA.getValue());
      System.out.println("oldA: " + oldA.getValue());

    }

}
0 голосов
/ 25 июня 2010

В последней строке вашего цикла вы пишете oldA=newA, поэтому oldA и newA имеют одинаковые ссылки.Таким образом, когда вы изменяете значение newA с помощью newA=new a(), значение oldA также изменяется (поэтому у вас будет oldA.x == newA.x).

Редактировать: я сделалнекоторые тесты, и я обнаружил, что то, что я сказал, было совершенно неправильно, извините за это.Однако код, данный ксенонитом, работает нормально.Условие newA.time != oldA.time выполнено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...