Можете ли вы получить предыдущее значение переменной в Java? - PullRequest
6 голосов
/ 04 марта 2009

Скажем, у переменной есть переменная (скажем, String Str), и значение Str начинается как "", затем, когда какой-то код выполняется, он устанавливается на "тестирование", а затем где-то еще в коде он снова изменяется, чтобы сказать " тестер». Теперь в программе я хочу узнать, каким было предыдущее значение Str. Возможно ли это на Java?

Итак, я говорю, что переменная менялась дважды, и вы хотите узнать, какой была Str, до того, как она была изменена во второй раз. Таким образом, в приведенном выше примере последним значением Str было бы «тестер», но я хотел выяснить, что Str был до этого (предполагая, что вы не знали, что это было до того, как он был изменен на тестер), в этом случае я бы хотел быть удалось выяснить, что Str был "тест".

Можно ли вообще сделать это на Java?

Ответы [ 14 ]

15 голосов
/ 04 марта 2009

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

11 голосов
/ 04 марта 2009

Не как родная часть языка, нет. Вы могли бы написать сеттер, который сохранил текущее (предыдущее?) Значение при изменении String.

private String str;
private String prev;

setStr(String s)
{
    prev = str;
    str = s;
}

Тогда просто напишите отдельный геттер для prev.

Конечно, это решение полагается на то, что вы всегда используете установщик для изменения значения str.

Кроме того, как указывает deworde , если вашей программе эта информация не нужна, вам не следует изменять ее для ее сохранения. Если вам нужна информация для отладки, вы можете просто установить часы в отладчике вашей IDE.

5 голосов
/ 04 марта 2009

Простой ответ, нет.

Однако вы можете использовать:

АОП

Фреймворк AOP, такой как AspectJ , может перехватывать присвоения переменной.

См. Ссылка на точку AspectJ

JavaBeans Поддержка изменения свойства

Вы могли бы использовать стандартные установщики JavaBean, геттеры для инкапсуляции вашего поля. Затем вы можете зарегистрировать слушателей в bean-компоненте для прослушивания изменений свойств и даже наложить вето на эти изменения.

См. JavaBean Spec для получения дополнительной информации.

Пример слушателя:

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;

public class MyBeanListener implements PropertyChangeListener,
        VetoableChangeListener {

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.printf("Notifed of property changed event: %s => %s%n", evt
                .getOldValue(), evt.getNewValue());

    }

    @Override
    public void vetoableChange(PropertyChangeEvent evt)
            throws PropertyVetoException {
        System.out.printf("Notified of vetoable change event: %s => %s%n", evt
                .getOldValue(), evt.getNewValue());
    }
}
4 голосов
/ 04 марта 2009

У вас уже есть два простых ответа:

  • Нет, сама Java не позволяет этого
  • Вы можете использовать сеттеры и реализовать механизм для сохранения старых значений

Но есть третий, который я до сих пор не видел:

Должна быть возможность написать Aspect в AspectJ, который срабатывает при назначении. Так что это будет иметь тот же эффект, что и сеттер, без фактического сеттера. Если вы работаете с кодом, который вы не хотите или не можете изменить, это может быть вариантом.

Обратите внимание, что, хотя AspectJ не является Java, результатом является обычный байт-код, поэтому он должен быть совместим с большинством сред.

Конечно, вместо использования AspectJ вы можете сделать это с CGLIB.

4 голосов
/ 04 марта 2009

Если вам действительно это необходимо, вы можете использовать следующий код:

public class Main 
{
    public static void main(final String[] argv) 
    {
        SavedValue<Integer> i;

        i = new SavedValue<Integer>();
        i.set(7);
        System.out.println(i.get());
        System.out.println(i.getOld());
    }
}

class SavedValue<T>
{
    private T oldValue;
    private T value;

    void set(final T val)
    {
        oldValue = value;
        value    = val;
    }

    T get()
    {
        return (value);
    }

    T getOld()
    {
        return (oldValue);
    }
}

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

2 голосов
/ 13 апреля 2016

Вы можете попытаться использовать структуру данных стека. Он сохранит все предыдущие значения в правильном порядке. Вы можете реализовать свой собственный или использовать java Collections один:

Deque<Integer> stack = new ArrayDeque<Integer>();

Каждый раз, когда вы устанавливаете переменную, кладите ее в стек (либо через сеттер, либо через AOP, как указано в других ответах). Таким образом, вы сможете получить доступ ко всем предыдущим значениям.

2 голосов
/ 04 марта 2009

Похоже, вы используете это для отладки, я прав?

Visual Studio или любой приличный отладчик должен позволять вам печатать трассировку значения каждый раз, когда оно устанавливается, просто помещая "точку трассировки" до и после всех вызовов, которые устанавливают значение.

Вы просто изменяете свойства обычной точки останова, чтобы печатать оператор, а не останавливать выполнение. В VS2005 это делается:

  • Вывод окна контрольной точки
  • Щелкните правой кнопкой мыши точку останова
  • Выбор опции «При попадании ...».
  • Выбор «Распечатать сообщение» и ввод сообщения
  • Убедиться, что «Продолжить выполнение» все еще выбрано.

Обычно это значительно замедляет работу программы во время отладки, поэтому она мало полезна для отладки, зависящей от времени; но это все еще позволяет мне следить за состояниями переменной (ABCDFEGH ...)

Конечно, если вы do хотите остановить выполнение, просто сбросьте обычную точку останова в.

1 голос
/ 04 марта 2009

В дополнение к тому, что сказал Стефан, я бы порекомендовал некоторую структуру List, содержащую все исторические ценности.

Если вы хотите изменить значение, просто добавьте новое значение в конец списка. Когда вы хотите получить текущее значение, просто посмотрите на последнее значение. Если вы хотите увидеть предыдущие значения, начните с конца списка.

1 голос
/ 04 марта 2009

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

0 голосов
/ 04 июля 2017

Да !! Когда вы изменяете значение, значение изменяется только для конкретного объекта. Смотрите пример:

 class Test{
int a=100; //original value 
 Test(int b){
    this.a=b;
 }
 Test(){
 }
void print(){
 System.out.println(a);
}
 public static void main(String args[]){
     Test t=new Test(9);
     Test t2=new Test();
     t.print();      //output: 9
     t2.print();     //output: 100 
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...