你能在 Java 中获取变量的先前值吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/610976/
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-29 13:03:58  来源:igfitidea点击:

Can you get the previous value of a variable in Java?

javavariables

提问by The Special One

Say way have a variable (let's say String Str) and the value of Str starts of as " " then as some code is running it is set to "test" then somewhere else in the code it is changed again to say "tester". Now in the program I want to find out what the previous value of Str was. Is this possible in Java?

说 way 有一个变量(比方说 String Str)并且 Str 的值以“”开头,然后当一些代码正在运行时,它被设置为“test”,然后在代码中的其他地方再次更改为“tester”。现在在程序中我想找出 Str 的先前值是多少。这在Java中可能吗?

So I am saying that the variable gets changed twice, and you want to find out what Str was before it got changed for the second time. So in the example above the latest value of Str would be "tester" but I wanted to find out what Str was before this (assuming you had no idea what it was before it was changed to tester) in this case I would want to be able to find out that Str was "test".

所以我是说变量被改变了两次,你想在它第二次改变之前找出 Str 是什么。因此,在上面的示例中,Str 的最新值将是“tester”,但我想找出 Str 在此之前是什么(假设您在更改为 tester 之前不知道它是什么)在这种情况下我想成为能够发现 Str 是“测试”。

Is it at all possible to do this in Java?

有可能在 Java 中做到这一点吗?

回答by Stefan Thyberg

No, it's not possible, you have to save the previous value before you change it to do what you're asking for.

不,这是不可能的,您必须先保存先前的值,然后再更改它以执行您所要求的操作。

回答by Bill the Lizard

Not as a native part of the language, no. You could write a setter that saved the current (previous?) value when the String changes, though.

不是作为语言的本地部分,不。不过,您可以编写一个 setter,在 String 更改时保存当前(上一个?)值。

private String str;
private String prev;

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

Then just write a separate getter for prev.

然后只需为prev.

Of course, this solution relies on you alwaysusing the setter to change the value of str.

当然,这个解决方案依赖于你总是使用 setter 来改变 的值str

Also, as dewordepoints out, if your program doesn't need this information, then you shouldn't modify your program to save it. If you need the information for debugging purposes you can just set a watch in your IDE's debugger.

此外,正如deworde指出的那样,如果您的程序不需要这些信息,那么您不应该修改您的程序来保存它。如果您需要信息用于调试目的,您可以在 IDE 的调试器中设置一个监视。

回答by toolkit

Simple answer, no.

简单的回答,没有。

However, you could use:

但是,您可以使用:

AOP

AOP

An AOP framwork, such as AspectJcould intercept assignments to a variable.

AOP 框架,例如AspectJ,可以拦截对变量的赋值。

See AspectJ pointcut reference

请参阅AspectJ 切入点参考

JavaBeansProperty Change Support

JavaBeans属性更改支持

You could use standard JavaBean setters, getters to encapsulate your field. Then you can register listeners on a bean to listen out for property changes, and even veto that change.

您可以使用标准的 JavaBean setter、getter 来封装您的字段。然后,您可以在 bean 上注册侦听器以侦听属性更改,甚至可以否决该更改。

See JavaBean Specfor more information.

有关更多信息,请参阅JavaBean 规范

Example listener:

示例侦听器:

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

回答by Jens Schauder

You already got the two simple answers:

你已经得到了两个简单的答案:

  • No, Java itself doesn't allow that
  • You can use setters and implement a mechanism to keep the old value(s)
  • 不,Java 本身不允许这样做
  • 您可以使用 setter 并实现一种机制来保留旧值

But there is a third one which I haven't seen so far:

但还有第三个我目前还没有看到:

It should be possible to write an Aspect in AspectJ that triggers on the assignment. So it would have a similar effect as a setter, without the actual setter. If you are working with code that you don't want to or cannot change this might be an option.

应该可以在 AspectJ 中编写一个触发分配的 Aspect。因此,如果没有实际的 setter,它将具有与 setter 类似的效果。如果您正在使用您不想或无法更改的代码,这可能是一个选项。

Note that while AspectJ isn't Java the result is normal byte code, so it should be compatible with most environments.

请注意,虽然 AspectJ 不是 Java,但结果是正常的字节码,因此它应该与大多数环境兼容。

Of course instead of using AspectJ you could do this with CGLIB.

当然,您可以使用 CGLIB 来代替 AspectJ。

回答by TofuBeer

If you really have a strong need for this you could use the following code:

如果您真的对此有强烈需求,可以使用以下代码:

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

Perhaps you could explain why you want the old value? I am sure we can give you much better answers if we knew why yoiu wanted it.

也许您可以解释为什么要使用旧值?如果我们知道你为什么想要它,我相信我们可以给你更好的答案。

回答by deworde

It looks like you're using this for debugging, am I right?

看起来您正在使用它进行调试,对吗?

Visual Studio, or any decent debugger should allow you to print a trace of the value every time it's set just by putting a "tracepoint" before and after all the calls that set the value.

Visual Studio 或任何不错的调试器应该允许您在每次设置值时打印该值的跟踪,只需在所有设置该值的调用之前和之后放置一个“跟踪点”。

You just alter the properties of a normal breakpoint to print a statement rather than halt execution. In VS2005 this is done by:

您只需更改普通断点的属性即可打印语句而不是停止执行。在 VS2005 中,这是通过以下方式完成的:

  • Bringing up the breakpoint window
  • Right-clicking on the breakpoint
  • Selecting the option "When Hit...".
  • Selecting "Print a Message" and entering a message
  • Making sure that "Continue Execution" is still selected.
  • 调出断点窗口
  • 右键单击断点
  • 选择选项“当命中...”。
  • 选择“打印信息”并输入信息
  • 确保仍选择“继续执行”。

This normally slows the program down significantly while debugging, so it's of little use for time-dependent debugging; but it's still allowed me to follow a variable's states (ABCDFEGH...)

这通常会在调试时显着降低程序的速度,因此它对于依赖于时间的调试几乎没有用;但它仍然允许我遵循变量的状态(ABCDFEGH ...)

Of course, if you dowant to halt execution, just dump a normal breakpoint in.

当然,如果您确实想停止执行,只需转储一个正常的断点即可。

回答by ACV

You may try to use a stack data structure. It will keep all previous values in the right order. You may implement your own or use the java Collections one:

您可以尝试使用堆栈数据结构。它将以正确的顺序保留所有先前的值。您可以实现自己的或使用 java Collections 之一:

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

Each time you set the variable, put it in the stack (either through setter or AOP as mentioned in the other answers). That way, you will be able to access al previous values.

每次设置变量时,将其放入堆栈中(通过其他答案中提到的 setter 或 AOP)。这样,您将能够访问所有以前的值。

回答by Kris

Indeed, this is not possible. You'd have to create your own String class that had some sort of memory to achieve this.

确实,这是不可能的。您必须创建自己的 String 类,该类具有某种内存来实现这一点。

回答by Kris

In addition to what Stefan said, I would recommend a List structure of some kind containing all the historical values.

除了 Stefan 所说的之外,我还建议使用某种包含所有历史价值的 List 结构。

When you want to change the value, just add a new value to the end of the list. When you want to get the current value, just look at the last value. If you want to see previous values, start from the end of the list.

当您想要更改该值时,只需在列表末尾添加一个新值即可。当您想获取当前值时,只需查看最后一个值即可。如果您想查看以前的值,请从列表的末尾开始。

回答by Tom Hawtin - tackline

If you could find the previous state of the program, there would never be any garbage to collect and the program would very quickly run out of memory.

如果您能找到程序的先前状态,则永远不会有任何垃圾要收集,并且程序将很快耗尽内存。

For specific variables, you could use, say, a LIFO stack. Instead of an assignment you would push to the stack. Instead of reading the variable, you would peek. The contents of the stack can be examined to find historical values.

对于特定变量,您可以使用 LIFO 堆栈。您将推送到堆栈而不是分配。你会偷看而不是阅读变量。可以检查堆栈的内容以查找历史值。

Another approach would be to use instrumentation. This allows you to, with sufficient skill and patience, rewrite byte code to do what ever you want.

另一种方法是使用检测。这使您能够以足够的技巧和耐心重写字节码以执行您想要的任何操作。

Perhaps you want to stand back a bit and look at what you are actually trying to achieve.

也许你想退后一点,看看你真正想要达到的目标。