gpt4 book ai didi

java - 在不使用外部调试器的情况下跟踪 java 程序中变量变化的简单方法

转载 作者:行者123 更新时间:2023-11-30 08:29:50 25 4
gpt4 key购买 nike

所以我创建了一个类,我可以将其包含在我的程序类中,并从一个 Thread 开始,它基本上会在某些变量发生变化时提醒我。我想知道是否有人有更好的想法来快速有效地获取此类信息,如果没有,他们是否对本类(class)有任何建议。仅供引用,alert() 方法基本上是一个简单的 System.out.println()。

public class OutputState extends Thread{

String className = this.getClass().toString().replace("class ","").replace("$OutputState","");
String[] desc = {"canvasWidth","canvasHeight","relativeCenterX","relativeCenterY","zoom","hAdjust","vAdjust"};
int[] delay = {0,0,99,99,0,0,0,};
Object[] var;
int maxDescLength = 0;

public void init(){
Object[] v = {canvasWidth,canvasHeight,relativeCenterX,relativeCenterY,zoom,hAdjust,vAdjust};
var = v;
}

public void run(){
init();
while(true){
boolean newLine = false;
Object[] v = {canvasWidth,canvasHeight,relativeCenterX,relativeCenterY,zoom,hAdjust,vAdjust};
for(int i = 0; i < var.length; i++){
if(maxDescLength < desc[i].length()){
maxDescLength = desc[i].length();
}
if(!var[i].equals(v[i])){
var[i]=v[i];
String spaces = " ";
int count = desc[i].length()+1;
while(count <= maxDescLength){
spaces += " ";
count++;
}
alert(className + "." + desc[i] + spaces + "= " + var[i]);
newLine = true;
if(delay[i] > 0){try{Thread.sleep(delay[i]);}catch(InterruptedException e){}}
}
}
if(newLine){
alert("------------------------------------");
}
try{Thread.sleep(1);}catch(InterruptedException e){}
}
}
}

基本概念是 v 设置为您要跟踪的变量,并将随着程序中不断变化的变量不断更新自身,而 var 将包含 OutputState 最后知道的内容。每当 v 中的任何内容发生变化时,var 都会捕获它并输出自定义消息。我知道很多人会发现像这样有用的东西,这让我相信可能有更好的方法我还没有找到。我将不胜感激任何意见!

最佳答案

没有一种简单的方法可以完成您想要做的事情。即使你循环(就像你现在正在做的那样),你不仅会减慢其余的计算速度(由于总线流量),而且还可能会错过一些更新(如果监视器线程的调度频率较低或更忙)处理器比工作线程)。

如评论中所述,您最好使用某种面向方面的编程语言、Java 代理或更简单的委托(delegate)模式。无论哪种方式,您都可能需要修改现有代码。

interface IWorkState {
//Declares the method of WorkState
}

class WorkState implements IWorkState {
//Whatever java bean
}

class WorkTask implements Runnable {
private final IWorkState state;

public void addStateObserver(IWorkState initialState) {
state = initialState
}

@Override
public void run() {
//Task instructions here
//instructions should operate on the state variable
}
}

class VarMonitor {
public void update(Object changed) {
//subject has changed, react to it
eventQueue.submit(/* a Runnable that handles the state change,
with embedded information about the change */);

}
}

class MainClass {
public static void main(String[] args) {
final VarMonitor mon = new VarMonitor();
WorkTask t = new WorkTask(Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {IWorkState.class}, new InvocationHandler() {
private final WorkState realWorkState = new WorkState();
Object invoke(Object proxy, Method method, Object[] args) {
Object res = method.invoke(realWorkState, args);
//An annotation would work better
if (method.getName().substring(0,3).equals("set")) {
mon.update(this);
}
}
});
}
}

第三种选择是使用 java.util.Observable 的子类,当然还有观察者模式。像这样的东西:

class WorkState extends java.util.Observable {
//A thread-safe observable java bean
}

class WorkTask implements Runnable {
private final WorkState state = new WorkState();

public void addStateObserver(Observer ob) {
state.addObserver(ob);
}

@Override
public void run() {
//Task instructions here
//instructions should operate on the state variable
}
}

class VarMonitor implements Observer {
private final ExecutorService eventQueue
= Executors.newSingleThreadExecutor();

@Override
public void update(Observable subject, Object info) {
//subject has changed, react to it
eventQueue.submit(/* a Runnable that handles the state change,
with embedded information about the change */);

}
}

如果您将此模式与不可变对象(immutable对象)一起使用,您可以轻松实现一个 ObservableReference 类,它适用于您的所有对象。

PS:之前没提过,多线程访问共享变量必须是同步的,或者变量要么是线程安全的,要么是volatile的。您不能盲目地轮询共享变量,否则您可能会得到一些错误的结果(例如看到部分更新的对象)。

关于java - 在不使用外部调试器的情况下跟踪 java 程序中变量变化的简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19051805/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com