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
How to watch a variable for changes
提问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 MyValueChangeListner
event 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 private
and 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 static
whenever possible. In particular public
but not final
.
附带说明一下,static
尽可能避免。特别public
但不是final
。
回答by Peter Lawrey
You need to replace the type int
with 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/
回答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.property和javafx.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 中。