So I have to write a program for an invoice where I define the variables locally, instead of globally. So it kinda looks like this the way I have it.
public void setAmount(int anyAmount)
{
int amount;
amount = anyAmount;
}
I then do the display method like this and get an error saying cannot find symbol
public void displayInvoice()
{
System.out.println("Amount: " + amount);
I can easily do this globally, but having troubles with this. Thank you!
When you declare a variable inside a function, such as in your setAmount, it only exists for as long as that function is executing; it only exists between the { and }. That's why you're unable to reference it later in the second function, as it no longer exists. Essentially, what you're doing is setting it, and then getting rid of it right away, through no effort on your code, but simply through the way memory is allocated and used in programs.
The way to get around this would be to use a "global" as you've said, or to pass it back after you set it, and put it into another variable, which you then send to your displayInvoice function. The last method requires that the setAmount and displayInvoice are part of a larger function themselves, and the intermediary variable is declared inside it. Over all, a "global" as you've said, is the easiest and probably best solution given what you've explained.
Unworking Example:
main() {
int amount = 0;
amount = setAmount(5);
displayInvoice(amount);
}
In doing so though, you may as well forgo the setAmount function, as you can see it's fairly redundant. Keeping set amount, you'd need to change it to
Public int setAmount(int anyAmount)
When you declare a variable inside a method it becomes local meaning it's only visible in that method, that is why you are getting that error, you can correct that by making it global.
Related
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;
}
}
I have a method that list the elements of an ArrayList, typically it prints the components of a global variable ArrayList, but in one specific instance I need it to print the components of a local variable.
So I have this
public static void listPlayers(ArrayList<Player> characters, boolean beingRolled) {
//print character components (beingRolled specifies which parts of each players to print
}
and I use that when I'm using the local variable ArrayList,
when I want to use the global i call this version
public static void listPlayers(boolean beingRolled) {
listPlayers(players, abitraryBoolean);
}
where players is the global variable
Another thing I was thinking about is anywhere I want to use the global I could pass a null reference for characters and write this method
public static void listPlayers(ArrayList<Player> characters, boolean beingRolled) {
if (characters == null) characters = players;
//print components
}
Which is the more professional/recommended version?
In general, stay away from null; the overloaded method signature is a better approach.
That said, one thing you said is scary -- You have a static method operating on a global variable. In general, that is a bad idea. You should consider refactoring to use Object/class scoped state, rather than global, static scoped state.
I would even go so far as to say that you should only use the overload that takes the ArrayList as a parameter, and pass it the global variable every time. Then, even if you must use a global variable, at least you're using it in one fewer place.
Edit: One of my professors back in college wrote a book on refactoring that is very readable and has a lot of good content (though the typography is a bit odd). It's called Principle-Based Refactoring: Learning Software Design Principles by Applying Refactoring Rules, by Steve Halladay. I highly suggest reading the first half (second half is essentially a reference).
The first version is better because it is easier for someone else to understand. When a function's arguments are all listed, the caller can more easily predict what the function will do. If the function relies on variables which are not visible, say if this is available in a library without the source, the caller will not understand why the function acts in an unexpected way. This would be impossible to understand without good documentation.
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"?
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...
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)));