How to block/bulk reset static variables using Java 7 - java

I am parsing a text file looking for syntax matches. to complete this task, I created Variable class with static variables in it. Then I parse a file and I assign the parsed information to the variable class static elements.
Variable.name = "the parsed information";
Then I created a Baseline class to check and compare against the Variable elements to check if certain condition is met.
For example
if (BaseLine.x.equal(Variable.x) // do whatever.
Variable Class:
public class Variable {
static String name;
static String userID;
static Integer age
}
BaseLine Class:
public class BaseLine {
static String name;
static String userID;
static Integer age
}
Utilizing JavaFX I move between scenes to load a file, parse it, assign the parsed variable then compare it with my BaseLine class. Thus far, Everything works as expected until I hit the back button to go back to the original scene to load a new file. now, the issue that I am having how can I reset the variable inside my Variable class in bulk instead of doing it one by one inside my controller initialize statement? I want to do this to ensure that I don't capture any variable from the older file I just parsed before I hit the back button. what is the correct way of completing this task?
I was able to get what I am looking for when I reset the variables inside my initialize controller, but it seems to be a lengthy process to do for OOP I have over 100 variables (int/sets/strings...) to reset.
Here is what I did to reset the static Variables inside the controller initialize section.
#Override
public void initialize(URL url, ResourceBundle rb) {
Variable.name = null;
Variable.setName.clear();
Variable.age = null;

I was able to get what I am looking for when I reset the variables inside my initialize controller, but it seems to be a lengthy process to do for OOP I have over 100 variables (int/sets/strings...) to reset.
If you have hundreds of static variables, you are not doing OOP properly. In proper OO design, your application's state should be held in instance variables, and accessed via instance variables. Static variables should be kept to an absolute minimum. (You can eliminate them entirely, if you can use a dependency injection (DI) framework ...)
The bad news is that there is no >>good<< way to reset a large number of
static variables. There are a couple of >>bad<< ways; e.g. reflection, and messing around with classloaders ... but you just would be replacing one problem (clunky code) with a worse one (complex, fragile code). IMO.
But the good news is that you fix your design / implementation to be properly OO, then you won't have this nasty problem of resetting the variables. And a whole bunch of other things will be easier too ... like writing unit tests.

I am not aware of a way that would exists that would allow you to reset all static variables in one go. You would have to do one by one.
I think your problem lies somewhere else - and i believe you should refactor your code in that instance (if possible).
How about having all your variables as standard (non static) and set/get them like you normally would but when done just create new object and let the old one be collected by Garbage collector??
Edit:
Although you could perhaps use reflection ? Not entirely sure if that would work though.
Something like
Field[] fields = MyClass.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers() && isRightName(field.getName()) {
field = null;
}
}

Related

How to set and get static variables from spark?

I have a class as this:
public class Test {
private static String name;
public static String getName() {
return name;
}
public static void setName(String name) {
Test.name = name;
}
public static void print() {
System.out.println(name);
}
}
Inside my Spark driver, I'm setting the name like this and calling the print() command:
public final class TestDriver{
public static void main(String[] args) throws Exception {
SparkConf sparkConf = new SparkConf().setAppName("TestApp");
// ...
// ...
Test.setName("TestName")
Test.print();
// ...
}
}
However, I'm getting a NullPointerException. How do I pass a value to the global variable and use it?
Ok, there is basically 2 ways to take a value known to the master to the executors:
Put the value inside a closure to be serialized to the executors to perform a task. This is the most common one and very simple/elegant. Sample and doc here.
Create a broadcast variable with the data. This is good for immutable data of a big size, so you want to guarantee it is send only once. Also good if the same data is used over and over. Sample and doc here.
No need to use static variables in either case. But, if you DO want to have static values available on your executor VMs, you need to do one of these:
If the values are fixed or the configuration is available on the executor nodes (lives inside the jar, etc), then you can have a lazy val, guaranteeing initialization only once.
You can call mapPartitions() with code that uses one of the 2 options above, then store the values on your static variable/object. mapPartitions is guaranteed to run only once for each partition (much better than once per line) and is good for this kind of thing (initializing DB connections, etc).
Hope this helps!
P.S: As for you exception: I just don't see it on that code sample, my bet is that it is occurring elsewhere.
Edit for extra clarification: The lazy val solution is simply Scala, no Spark involved...
object MyStaticObject
{
lazy val MyStaticValue = {
// Call a database, read a file included in the Jar, do expensive initialization computation, etc
4
}
}
Since each Executor corresponds to a JVM, once the classes are loaded MyStaticObject will be initialized. The lazy keyword guarantees that the MyStaticValue variable will only be initialized the first time it is actually requested, and hold its value ever since.
The copy of your class in your driver process isn't the copy in your executors. They aren't in the same ClassLoader, or even the same JVM, or even on the same machine. Setting a static variable on the driver does nothing to the other copies, hence you find it null remotely.
I would like to add one more approach this makes sense only when if you have a few variables which cab ne passed in runtime as arguments.
spark Configuration --> --conf "spark.executor.extraJavaOptions=-DcutomField=${value}"
and
when you need data in transformations you can call System.getProperty("cutomField");
you can find more details here
Note: above discussed does not make sense when we have a significant number of variables
. in those cases, I would prefer #Daniel Langdon approaches.
I would like to add one more point into DanielL's Answer
When declare a variable with static keyword the JVM loads it during the class loading so if you create a jar and set initial values of static fields in a Java /scala class are stored in the jar, workers can use it directly. However if you change the value of a static field in the driver program, workers can only see the initial value assigned into Jar and your changed value will not reflect , so you need to copy again new jar or need to copy class manually into all executors .

Java - Remove "Variable", keep assignments with side effects

I am starting to develop for Android (And I am starting to think, does it worth it!). Eclipse keeps giving me a lot of strange warnings and errors too! Here is one that kept me frustrated for the last two hours with no luck on Google:
private String alertTitle= null;
There is an ! mark beside it saying Remove "alertTitle", keep assignments with side effects. What is this?! I am defining a variable exactly as Java states. I am using the variable later:
public ASAlertDialog setTitle(String title) {
this.alertTitle = title;
return this;
}
Another one that's a little bit similar is defining enum"
public enum MyStyles {
aStyle;
}
public MyStyles myStyle = aStyle;
This made Eclipse angry!
You may be using the variable name by assigning a value to it, but you are not using the value stored in the variable. To do that, you must use the variable name to retrieve the stored value, and do something with this retrieved value somewhere in your code.
Eclipse tags the variable as unused when the value is never retrieved (or more generally, it's never possible to retrieve it*). It means you're merely assigning values to it, but never making use of them anywhere. This makes the variable an unnecessary memory hog, hence the warning.
* public and protected variables won't get the warning because they can be retrieved in other classes even if they aren't retrieved within the class they are declared in, and even if they are currently never retrieved in any class (it may happen in the future due to library use).
For the enum, it should be:
public MyStyles myStyle = MyStyles.aStyle;
This is because an enum is something like a class, with the constants acting similar to static variables in the class. (This is just an analogy, not exact an language definition.) You would retrieve enum constants the same way you retrieve variables from an external class that are defined as static.
Your variable is not used, so eclipse informs you about that and therefore you get message Remove "alertTitle", keep assignments with side effects
For enums, you need to declare it as
public enum MODE
{
NO_ASYNC_TASK,
NO_DOWNLOADED_DRAWABLE,
CORRECT
};
Check my this answer for more information
And the warning is because you might not be using alertTitle variable after declaring it.
To your first question:
It just means that your variable isn't being used, so you can safely remove it. The warning will disappear once you start using the variable in your code. Side-effects are explained here:
http://www.cs.umd.edu/~clin/MoreJava/Intro/assign.html
Check under "Is Assignment an Expression?"
To your second question:
There is no ';' in defining an enum. Check this:
http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
Try
public enum MyStyles {
aStyle;
}
public MyStyles myStyle = aStyle;
Regarding to your String, maybe Eclipse informs you that your variable is never used.
By the way,
private String alertTitle;
is null by default, so why do you set "= null"?

pattern for getting around final limitation of Java closure

I'm trying to write a very simple piece of code and can't figure out an elegant solution to do it:
int count = 0;
jdbcTemplate.query(readQuery, new RowCallbackHandler() {
#Override
public void processRow(ResultSet rs) throws SQLException {
realProcessRow(rs);
count++;
}
});
This obviously doesn't compile. The 2 solutions that I'm aware of both stink:
I don't want to make count a class field because it's really a local variable that I just need for logging purposes.
I don't want to make count an array because it is plain ugly.
This is just silly, there got to be a reasonable way to do it?
A third possibility is to use a final-mutable-int-object, for example:
final AtomicInteger count = new AtomicInteger(0);
....
count.incrementAndGet();
Apache Commons also have a MutableInteger I believe, but I have not used it.
You seem to already be aware of the solutions (they are different though); and you are probably aware of the reasons (it cannot capture local variables by reference because the variable might not exist by the time the closure is run, so it must capture by value (have multiple copies); it is bad to have the same variable refer to different copies in different scopes that each can be changed independently, so they cannot be changed).
If your closure does not need to share state back to the enclosing scope, then a field in the class is the right thing to do. I don't understand what your objection is. If the closure needs to be able to be called multiple times and it needs to increment each time, then it needs to maintain state in the object. A field (instance variable) properly expresses the storing of state in an object. The field can be initialized with the captured value from the outside scope.
If your closure needs to share state back to the enclosing scope (which is not a very common situation), then using a mutable structure (like an array) is the right thing to do, because it avoids the problem of the lifetime of the local variable.
I typically make count a class field but add a comment that it is only a field because it is used by an inner closure, Runnable etc...

static variable lose its value

I have helper class with this static variable that is used for passing data between two classes.
public class Helper{
public static String paramDriveMod;//this is the static variable in first calss
}
this variable is used in following second class mathod
public void USB_HandleMessage(char []USB_RXBuffer){
int type=USB_RXBuffer[2];
MESSAGES ms=MESSAGES.values()[type];
switch(ms){
case READ_PARAMETER_VALUE: // read parameter values
switch(prm){
case PARAMETER_DRIVE_MODE: // paramet drive mode
Helper.paramDriveMod =(Integer.toString(((USB_RXBuffer[4]<< 8)&0xff00)));
System.out.println(Helper.paramDriveMod+"drive mode is selectd ");
//here it shows the value that I need...........
}
}
//let say end switch and method
}
and the following is an third class method use the above class method
public void buttonSwitch(int value) throws InterruptedException{
boolean bool=true;
int c=0;
int delay=(int) Math.random();
while(bool){
int param=3;
PARAMETERS prm=PARAMETERS.values()[param];
switch(value){
case 0:
value=1;
while(c<5){
Thread.sleep(delay);
protocol.onSending(3,prm.PARAMETER_DRIVE_MODE.ordinal(),dataToRead,dataToRead.length);//read drive mode
System.out.println(Helper.paramDriveMod+" drive mode is ..........in wile loop");//here it shows null value
}
//break; ?
}
}
//let say end switch and method
}
what is the reason that this variable lose its value?
Could I suggest that to pass data between classes, you use separate objects instead of a global variable?
It's not at all clear how you expect the code in protocolImpl to get executed - as templatetypedef mentions, you haven't shown valid Java code in either that or the param class (neither of which follows Java naming conventions).
A short but complete example would really help, but in general I would suggest you avoid using this pattern in the first place. Think in terms of objects, not global variables.
As I understand it, a "Class" (Not just an instance but the entire class object) Can be garbage collected just like any other unreferenced object--a static variable in that class instance won't prevent the GC from collecting your class.
I just came here because I think I'm seeing this behavior in a singleton and I wanted to see if anyone else noticed it (I've never had to research the problem before-and this knowledge is like a decade old from the back of my brain so I'm unsure of it's reliability at this point).
Going to go continue research now.
Just found this question, check the accepted answer--looks like it's unlikely that a static will be lost due to GC, but possible.
Are static fields open for garbage collection?
A Variable never "loses" its value. You set it to "null" somewhere, but your code here is not enough to tell whats going on. The only place here where you set it is this line:
Helper.paramDriveMod =(Integer.toString(((USB_RXBuffer[4]<< 8)&0xff00)));
But if you pass "null" to toString() you get some null pointer exception...so I would assume that this line never gets hit and so you get the "null" value as you dont initialize paramDriveMod with some other value.
Don't use static variable until you are in some critical situation. You can use getter setter instead
Could it be that you may be confusing static with final? Static variables' values can change. Final variables' values can not.
The execution flow not shown - may be the 3rd code:
while(c<5){
Thread.sleep(delay);
protocol.onSending(3,prm.PARAMETER_DRIVE_MODE.ordinal(),dataToRead,dataToRead.length);//read drive mode
System.out.println(Helper.paramDriveMod+" drive mode is ..........in wile loop");//here it shows null value "
is executed before the second code
switch(ms)
{
case READ_PARAMETER_VALUE: // read parameter values
switch(prm){
case PARAMETER_DRIVE_MODE: // paramet drive mode
Helper.paramDriveMod =(Integer.toString(((USB_RXBuffer[4]<< 8)&0xff00)));

How to refactor global variables out of your code

The discussion around global variables and their misuse seems to hold a certain dogmatic tone to it. I am not here to dispute the "globals are bad" concept as it makes sense to me why they are bad. However I was wondering if people had some interesting code snippets that demonstrate exactly how to effectively refactor higher scoped variables and objects out of the code. In this question I am looking for examples or patterns of generic but useful solutions to the "I need to use a global variable here because it is easy" problem.
Here is a hypothetical and perhaps contrived example. I am using the global variable to keep track of the parameters sent to a function. And then if there is a failure that happens further down the chain I could go back and call the function again using parameters from the global variable.
public var myGlobalState:Object = new Object();
public function addPerson (name:String, person:Object, personCount:int, retryCount:int):void
{
myGlobalState = null; // Clear out old values
myGlobalState = new Object();
myGlobalState.name = name;
myGlobalState.person = person;
myGlobalState.personCount = personCount;
myGlobalState.retryCount = retryCount;
person.userId = personCount + 1;
person.name = name;
savePerson(person);
}
public function savePerson (person:Object):void
{
// Some code that attempts to save the person object properties to a database...
// The process returns a status code for SUCCESS of FAILURE.
// CODE TO SAVE TO DATABASE ....
// Return status code...
if (status == "fail")
{
// Retry at least once by calling the addPerson function again
if (myGlobalState.retryCount < 3)
{
addPerson (myGlobalState.name, person, myGlobalState.personCount, myGlobalState.retryCount);
}
}
}
I don't have a snippet, but I have a real world example.
Linear calibration constants (mass spectrometry field) in an
application were global and there was complicated code to
store and restore the global calibration constants for
different spectra. Usage of the two values was spread all
over the program, and it was difficult to change or check
that conversion between uncalibrated and calibrated mass
values using the two constants was correct in all cases.
I refactored by encapsulating the two calibration constants
in a class that had the responsibility of converting between
uncalibrated and calibrated mass values. Functions to do the
conversion were also introduced so it was centralised in one
place in the program instead of being spread all over the
program. This encapsulation later made it easy to introduce
a new kind of calibration (not linear).
Instead of accessing the two global variables the class
that represented a spectrum would instead have and use an
instance of the new calibration class, each instance with
its own set of calibration constants.
A quick solution would be by adding all your global variables inside one huge object, possibly with several child objects to separate the groups of data. With all those variables in one object, all you would need is one global variable to store this object. All your code would then refer the variables in this object instead the global variables.
The next step would be getting rid of this single, global object. And that should be easier than getting rid of a few hundreds of global variables. This could be done by changing it into an additional parameter that you pass along to any other methods.
Once all global data is gone, you can think about refactoring your code, trying to optimize this shared object by e.g. dividing it into multiple smaller objects. But by moving everything inside a single object, you make it all easier to manage.
The answer usually lies in the architecture of your program. You could design in in a way global variables are absolutely necessary and you could design in in the way you never need them. You would usually end up with a better and cleaner architecture in the later scenario plus would avoid all of the usual problems with creating unit tests for the methods which rely on the global variables etc.
This question will also help.
P.S. In your particular scenario the global variable is not really needed at all - you could easily pass it as a parameter to the addPerson method.

Categories

Resources