如何观察变量的变量

时间:2012-09-12 10:54:44

标签: java variables reflection

我想知道是否有任何方法可以让我在程序运行时观察变量值的变化。当然不使用调试器我想这样做以编程方式。例如:

class A
{
   public static int valueToBeWatched;
}

因此,在运行时,如果在我的项目中的任何类的任何方法中修改此值MyValueChangeListner,则应调用该事件。

4 个答案:

答案 0 :(得分:11)

你做不到。 Java本身没有内置的watch-on-modification钩子。 显然,你可以做民意调查。但那时它不会“活着”。

AspectJ 可以允许这样的思考,但我不确定它是否适用于原始变量,或者仅当你使用getter和setter时。

干净的Java方法是创建变量private并使用getter和setter。

private valueToBeWatched;

public void setValue(int newval) {
  valueToBeWatched = newval;
  notifyWatchers();
}

public int getValue() {
  return valueToBeWatched;
}

在旁注中,尽可能避免使用static。特别是public但不是final

答案 1 :(得分:6)

您需要将类型int替换为一个类,只要值发生变化,它就会调用您的侦听器。您可能希望在实际没有更改时忽略设置值。

e.g。

 private int value;
 private final MyValueChangeListener listener;

 public void setValue(int value) {
    if(this.value == value) return;
    listener.changed(this, this.value, value);
    this.value = value;
 }

您可以使用字节码注入执行此替换,但更改原始代码非常简单。

另一种方法是监视值以定期查找更改。除非价值变化非常缓慢,否则您可能看不到每一个变化。您可以使用调试器API执行此操作,但这并不简单,除非您已熟悉API,否则我建议您不要使用它。

Java调试器API链接

http://java.sun.com/javase/technologies/core/toolsapis/jpda/

http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/

http://docs.oracle.com/javase/6/docs/jdk/api/jpda/jdi/

答案 2 :(得分:4)

如果您可以使用Oracle提供的最新Java SE JDK,那么我建议使用 javafx.beans.property javafx.beans.value API。

以下是一些基本代码:

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;

public class ObservableValues
{        

    public static void main(String[] args) 
    {
        DoubleProperty dp = new SimpleDoubleProperty(9);
        dp.addListener( new DoubleChangeListener() );
        dp.setValue(3);
        dp.setValue(6);
    }

    static class DoubleChangeListener implements ChangeListener<Number>
    {
        @Override
        public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue) 
        {
            System.out.println("the value has changed from " + oldValue + " to " + newValue);
        }
    }

}

这是输出:

该值已从9.0更改为3.0

该值已从3.0更改为6.0

答案 3 :(得分:1)

如上所述,问题可以通过编写代理来收听所提供字段的更改来解决(请参阅fieldWatch)。代理必须使用C调用兼容语言进行编译,并在VM启动时使用-agentpath:<path-to-agent>=<options>开关调用。

更高级别的选项是使用JPDA / JDI附加到正在运行的进程,该进程将上述调用包装在(Java)ModificationWatchpointEvent中。