java 如何观察变量的变化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12386604/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 08:41:16  来源:igfitidea点击:

How to watch a variable for changes

javavariablesreflection

提问by Dangling Piyush

I want to know if there's any way so I could watch for variable value change when the program is running. Of course not using debugger I wanna do it Programmatically. For example:

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

class A
{
   public static int valueToBeWatched;
}

So at runtime if in any method of any class in my project modifies this value MyValueChangeListnerevent should get called.

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

回答by Has QUIT--Anony-Mousse

You cannot. There is no watch-on-modification hook built into Java itself. Obviously, you could do polling, though. But then it won't be "live".

你不能。Java 本身没有内置 watch-on-modification 钩子。显然,您可以进行轮询。但它不会是“活的”。

AspectJ mayallow such a think, but I'm not sure whether it holds for primitive variables, or only when you are using getters and setters.

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

The clean Java-way is to make the variable privateand use getters and setters.

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

private valueToBeWatched;

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

public int getValue() {
  return valueToBeWatched;
}

On a side note, avoid staticwhenever possible. In particular publicbut not final.

附带说明一下,static尽可能避免。特别public但不是final

回答by Peter Lawrey

You need to replace the type intwith a class which will invoke your listener whenever the values changes. You might like to ignore setting the value when it hasn't actually changed.

您需要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;
 }

You can perform this replace using byte code injection, but it is much simple to change the original code.

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

An alternative is to monitor the value to look for changes periodically. Unless the value changes very slowly you might not see every change. You can use the Debugger API to do this but it not simple and I wouldn't suggest you use it unless you are familiar with the API already.

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

Java Debugger API Links

Java 调试器 API 链接

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

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/technotes/guides/jpda/

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

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

回答by onebeartoe

If you can use the latest Java SE JDK from Oracle, then I suggest using the javafx.beans.propertyand javafx.beans.valueAPIs.

如果您可以使用 Oracle 的最新 Java SE JDK,那么我建议使用javafx.beans.propertyjavafx.beans.valueAPI。

Here is some basic code:

下面是一些基本代码:

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

}

Here is the output:

这是输出:

the value has changed from 9.0 to 3.0

该值已从 9.0 更改为 3.0

the value has changed from 3.0 to 6.0

该值已从 3.0 更改为 6.0

回答by tucuxi

The question, as stated, can be solved by writing an Agent to listen to changes on the provided field (see fieldWatch). The Agent would have to be compiled using a C-calling-compatible language, and invoked on VM start with an -agentpath:<path-to-agent>=<options>switch.

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

A higher-level option is to attach to a running process using JPDA/JDI, which wraps the above call in a (Java) ModificationWatchpointEvent.

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