重新分配一个值给方法内的实例变量,通过重新分配方法参数的变量。

huangapple go评论78阅读模式
英文:

Reassigning a value to an instance variable inside of a method by reassigning the method argument's variable

问题

我的类有一个定时方法,每隔半秒运行一次,它检查数据,看看是否有任何设备超时。如果它们超时至少5秒,我会向我的数据库抛出一个事件(这是通过checkSpecs方法完成的,我没有在这里复制)。实际的类非常大,所以我尝试减小大小,同时保持相关部分。

现在我正在向类中添加一个新方法checkReconnections,我希望使用它来在先前超时的连接重新获得时向数据库抛出另一个事件。

因为我的类非常大,我使用了一个辅助方法monitorConnectionStatus,接受两个布尔值作为参数。我的问题与这个方法有关。

我曾以为,当在调用方法时将实例变量传递给monitorConnectionStatus时,该方法可以访问它们并重新分配这些变量。这是我的意图,以使方法能够按预期运行。但我的IDE告诉我,disconnectionStatus的值将始终为false,这让我想,我是否错误地认为实例变量将被重新分配?我的IDE在这种情况下可能是错误的吗?

当我重新分配disconnectionStatus的值时,它是否会重新分配实例变量hasADisconnected的值,还是只是使用一个局部参数变量进行操作?

Public Class OffSpecAgent {
    private final DataModel dataModel;

    private int deviceATimeoutCounter = 0;
    private boolean isDeviceATimeout = false;
    private boolean hasADisconnected = false;

    private int deviceBTimeoutCounter = 0;
    private boolean isDeviceBTimeout = false;
    private boolean hasBDisconnected = false;

    @Scheduled(fixedDelay = 500)
    public void offSpecMonitor() {
        checkTimeouts();
        checkReconnections();
        checkSpecs();
    }

    private void checkTimeouts() {
        deviceATimeoutCounter = dataModel.getBoolean(DEVICE_A_TIMEOUT) ? deviceATimeoutCounter + 1 : 0;
        isDeviceATimeout = deviceATimeoutCounter >= 10;

        deviceBTimeoutCounter = dataModel.getBoolean(DEVICE_B_TIMEOUT) ? deviceBTimeoutCounter + 1 : 0;
        isDeviceBTimeout = deviceATimeoutCounter >= 10;
    }

    private void checkReconnections() {
        monitorConnectionStatus(isDeviceATimeout, hasADisconnected);
        monitorConnectionStatus(isDeviceBTimeout, hasBDisconnected);
    }

    private void monitorConnectionStatus(boolean timeoutCondition, boolean disconnectionStatus) {
        if (timeoutCondition) {
            disconnectionStatus = true;
        }
        if (disconnectionStatus && !timeoutCondition) {
            disconnectionStatus = false;
            //throw reconnection event
        }
    }
}
英文:

My class has a scheduled method that runs every half a second and it checks the data to see if any of the devices have timed out. If they are timed out for at least 5 seconds I am throwing an event to my database (this is done by checkSpecs method which I haven't reproduced here. The actual class is quite large so I have attempted to reduce the size while keeping relevant parts).

Now I am adding a new method to the class, checkReconnections which I want to use to throw another event to the database whenever a connection that previously timed out is regained.

Because my class is so large and I am monitoring several devices with this method, I attempted to create a helper method monitorConnectionStatus that accepts two booleans as arguments. My question is concerning this method.

I was under the impression that in passing the instance variables into monitorConnectionStatus when the method is invoked, that method gains access to them and can reassign those variables. This is my intent in order for the method to function as intended. But my IDE is telling me that the value of disconnectionStatus will always be false, which caused me to think, am I wrong in believing the instance variable will be reassigned? Is it possible that my IDE is just wrong in this case?

When I reassign the value of disconnectionStatus is it reassigning the value of the instance variable hasADisconnected or is it just doing it with a local argument variable?


Public Class OffSpecAgent {
    private final DataModel dataModel;

    private int deviceATimeoutCounter = 0;
    private boolean isDeviceATimeout = false;
    private boolean hasADisconnected = false;

    private int deviceBTimeoutCounter = 0;
    private boolean isDeviceBTimeout = false;
    private boolean hasBDisconnected = false;

    @Scheduled(fixedDelay = 500)
    public void offSpecMonitor() {
        checkTimeouts();
        checkReconnections();
        checkSpecs();
    }

    private void checkTimeouts() {
        deviceATimeoutCounter = dataModel.getBoolean(DEVICE_A_TIMEOUT) ? deviceATimeoutCounter + 1 : 0;
        isDeviceATimeout = deviceATimeoutCounter >= 10;

        deviceBTimeoutCounter = dataModel.getBoolean(DEVICE_B_TIMEOUT) ? deviceBTimeoutCounter + 1 : 0;
        isDeviceBTimeout = deviceATimeoutCounter >= 10;
    }

    private void checkReconnections() {
        monitorConnectionStatus(isDeviceATimeout, hasADisconnected);
        monitorConnectionStatus(isDeviceBTimeout, hasBDisconnected);
    }

    private void monitorConnectionStatus(boolean timeoutCondition, boolean disconnectionStatus) {
        if (timeoutCondition) {
            disconnectionStatus = true;
        }
        if (disconnectionStatus && !timeoutCondition) {
            disconnectionStatus = false;
            //throw reconnection event
        }
    }
}

答案1

得分: 1

在Java中,变量被按值传递到方法中,这意味着您的方法monitorConnectionStatus只知道它正在接收false, false的值。您需要更新您的方法以直接访问实例变量。

private void monitorConnectionStatus() {
    if (timeoutCondition) {
        disconnectionStatus = true;
    }
    if (disconnectionStatus && !timeoutCondition) {
        disconnectionStatus = false;
        // 抛出重新连接事件
    }
}

请注意,关键字this不是必需的。

此外,我只想补充一下,您错误地使用了术语类变量。您所指的变量应该是实例变量

您可以在这里阅读更多信息:

https://www.tutorialspoint.com/What-are-class-variables-instance-variables-and-local-variables-in-Java

英文:

In java, variables are passed by value into methods, meaning your method monitorConnectionStatus is only aware that it's getting false, false values. You would have to update your method to access the instance variable directly.

private void monitorConnectionStatus() {
    if (this.timeoutCondition) {
        this.disconnectionStatus = true;
    }
    if (this.disconnectionStatus && !this.timeoutCondition) {
        this.disconnectionStatus = false;
        //throw reconnection event
    }
}

Note the keyword this is not required.

Also, I just want to add that you are using the term class variable incorrectly. The variables you are referring to are instance variables.

You can read more about that here:

https://www.tutorialspoint.com/What-are-class-variables-instance-variables-and-local-variables-in-Java

答案2

得分: 0

我重构了这个类,现在它看起来像这样:

public class OffSpecAgent {
    private final DataModel dataModel;

    private static class ConnectionTracker {
        boolean timeout, timeoutExceeded, hasDisconnected;
        int timeoutCounter = 0;
    }

    private final ConnectionTracker deviceATracker = new ConnectionTracker();
    private final ConnectionTracker deviceBTracker = new ConnectionTracker();

    @Scheduled(fixedDelay = 500)
    public void offSpecMonitor() {
        checkTimeouts();
        checkReconnections();
        checkSpecs();
    }

    private void checkTimeouts() { 
        trackTimeout(deviceATracker, dataModel.getBoolean(DEVICE_A_TIMEOUT), 10);
        trackTimeout(deviceBTracker, dataModel.getBoolean(DEVICE_B_TIMEOUT), 20);
    }

    private void trackTimeout(ConnectionTracker tracker, boolean isTimeout, int maxTimeout){
        tracker.timeout = isTimeout;
        tracker.timeoutCounter = isTimeout ? tracker.timeoutCounter + 1 : 0;
        tracker.timeoutExceeded = tracker.timeoutCounter >= maxTimeout;
    }

    private void checkReconnections() {
        monitorConnectionStatus(deviceATracker);
        monitorConnectionStatus(deviceBTracker);
    }

    private void monitorConnectionStatus(ConnectionTracker tracker) {
        if (tracker.timeoutExceeded) {
            tracker.hasDisconnected = true;
        }
        if (tracker.hasDisconnected && !tracker.timeout) {
            tracker.hasDisconnected = false;
            //throw reconnection event
        }
    }
}

这似乎是一个很大的改进,tracker 对象实际上让代码更易读,现在我能够实现所需的行为。感谢回答我的问题的每个人。

英文:

I refactored the class and now it looks like this:

Public Class OffSpecAgent {
private final DataModel dataModel;
private static class ConnectionTracker {
boolean timeout, timeoutExceeded, hasDisconnected;
int timeoutCounter = 0;
}
private final ConnectionTracker deviceATracker = new ConnectionTracker();
private final ConnectionTracker deviceBTracker = new ConnectionTracker();
@Scheduled(fixedDelay = 500)
public void offSpecMonitor() {
checkTimeouts();
checkReconnections();
checkSpecs();
}
private void checkTimeouts() { 
trackTimeout(plcTracker, dataModel.getBoolean(DEVICE_A_TIMEOUT), 10);
trackTimeout(plcTracker, dataModel.getBoolean(DEVICE_B_TIMEOUT), 20);
}
private void trackTimeout(ConnectionTracker tracker, boolean isTimeout, int maxTimeout){
tracker.timeout = isTimeout;
tracker.timeoutCounter = isTimeout ? tracker.timeoutCounter + 1 : 0;
tracker.timeoutExceeded = tracker.timeoutCounter >= maxTimeout;
}
private void checkReconnections() {
monitorConnectionStatus(deviceATracker);
monitorConnectionStatus(deviceBTracker);
}
private void monitorConnectionStatus(ConnectionTracker tracker) {
if (tracker.timeoutExceeded) {
tracker.hasDisconnected = true;
}
if (tracker.hasDisconnected && !tracker.timeout) {
tracker.hasDisconnected = false;
//throw reconnection event
}
}
}

This seems to be much of an improvement, the tracker object actually makes the code more readable in my opinion, and now I am able to have the desired behavior. Thank you to everyone who responded to my question.

huangapple
  • 本文由 发表于 2020年8月7日 04:15:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/63291139.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定