System.setProperty or public static variable? - java

I understand that System.setProperty(“key”,”value”) and System.getProperty(“key”) are used to hold and retrieve system properties and user-defined properties. The values set can be accessed everywhere within the application.
Also, I am aware that when a variable is declared public and static, it becomes a constant and is available everywhere within the application.
I would like to know of the 2 which is advantageous and a better option. One aspect I could think of is System.setProperty is useful when we want to retrieve a value in an xml file[using ${key}]. The same can not be achieved using public static variable.
My questions are
Are there any other benefits?
Which one is a better option?
On what scenarios should one go with System.setProperty/getProperty and public static variable?
Thanks in advance.

A Setter can have further tests. Like testing against null, test against bad values etc...
A Setter is usually a better option, yet, a class without Setters could be even better, don't give the user ways of destroying your program
public static Variable variable;
//In other file
variable = null;
And public static variables are not thread-safe at all!!!(Maybe if it's atomic)
Unless dealing with something I really want to be changed a lot, like a Vector2D/3D I never use public static (and in this cases it's not public static anyway because it isn't static). To add to this, I only make it because the user can't null out x,y,z because it's a float/int. Usually I go with methods that do what I want and not simple Setters.
(Ex: Not a good example but I think it shows what I meant. Instead of Person.setState(State.EATING) using Person.eat())

When you run a java program, you are actually starting a JVM instance. That instance will have it's own System properties. That is where you can put your properties. When you run another program, it will have it's own System properties.
A Properties object is a sub-type of Hash-table and it is also thread-safe. But if you want to use a public static variable you also have to handle synchronous access in multi-threaded programs.

Related

Is there a workaround for running multiple instances of a class with static variables in Java?

I'm working on an existing piece of simulator software, and the structure is basically like this (it has a static member variable containing itself):
public class Simulator {
private Static Simulator instance;
public Simulator(){
instance = this;
//blah
//blah
//other things
}
}
And then a lot of methods access the static instance of the Simulator like this:
for(Foo f : Simulator.instance.getFoo() ){
//blah
}
You get this idea. Basically, the programmers who came before me assumed that there would only ever be one single instance of the Simualtor, so they made it accessible statically.
The problem is that I now want to run multiple instances of it, so this static part is becoming annoying.
Making this work without it being static is probably the best option, I know, but as you can imagine it will take a lot of refactoring and time.
The one thing that does work is to run multiple main methods (so run it several times in my IDE, or run it as a .jar in separate windows). I assume this is because each main method or JVM instance or whatever is acting as a sort of container, so the statics don't interfere?
What I was wondering was, is there a hacky workaround that I can use (at least short-term) to create multiple instances of the simulator, but within some kind of container that makes the static instances not interfere.
I think this is possible using Java class loaders (ClassLoader), but this will lead you into a world of pain. You would have to create sub-applications each using different class loaders. I have never done this, but I believe this is how application servers work.
It will be far easier to refactor your application.
Instead of accessing instance you would have to create multiple instance variables or some dynamic registry like a map where you store the references.
By-the-way, the way that instance is stored in the constructor is very bad practice as it will get overwritten each time new is called and the previous version will be lost. Usually, you would want to just initialise instance with an object.
The quickest and hacky way that I could think of is to override that constructor with a dummy variable
public Simulator(Boolean isDummy){
}
Now you have the option to create a multiple instance of that class without affecting others. Not sure if the parameter overhead is acceptable in your case.

Why is it better to use class name instead of objects to access class methods or variables in Java?

I was reading Code Conventions for Java from http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-137265.html#587.
In that, they have mentioned that we should avoid the use of objects to access a class variable or a method and should we use the class name instead.
Avoid using an object to access a class (static) variable or method.
Use a class name instead. For example:
classMethod(); //OK
AClass.classMethod(); //OK
anObject.classMethod(); //AVOID!
Is there a particular reason for this in terms or performance or something else?
By class variables I assume you mean static variables.
The use of static variables/methods through instance variables should be avoided because it's confusing to the reader. Since you can only use instances to access instance variables, reading a code that calls static methods through an instance can confuse the reader about what's going on.
Image this case, with Thread.sleep, which is a static method:
Thread.sleep(1000);
Since the method is static and we are calling it through the class name, it's intuitive to the reader to deduce that the effect is to put the current thread to sleep.
Now if we did this:
Thread t = new Thread(...);
t.sleep(1000);
Now which thread is put to sleep? The current one "obviously". Someone not knowing about how sleep works might think that the child thread is somehow put to sleep.
I guess it depends on what you want to do.I for one always use the class name to acces a static variable.Being static it doesn matter the way you do it, but i does save some memory usage.
As for nonstatic variables, always use objects.
It is not any different in terms of the bytecode that's produced, so performance is not the issue.
What is the issue is that using a variable to access static members looks as if the reference held by the variable actually matters to what is being accessed. But it does not! In fact even if anObject where null, you would not get a NPE, but it would just call classMethod.
So the principle is simple: when accessing static members, avoid mentioning information (in this case the variable name) that's actually not relevant to the access being made.
I don't know about performance, but clearly another developper looking your code will know at first sight its a static variable/method if you use it with the classname.
I don't think compiler will give different code using a variable though.
it's because.
1.It tells that the variable or method is a static actually.
2.Also, its checked that the object refers to which class. that incurs extra cost.

Writing to a static variable in an instance method, why is this a bad practice?

I am a little confused here with this findbugs warning in eclipse.
public class MyClass {
public static String myString;
}
public class AnotherClass {
public void doSomething() {
MyClass.myString = "something";
}
}
This gives me a findbugs warning "write to static field from instance method", however this does not give me a warning:
public class MyClass {
public static String myString;
}
public class AnotherClass {
public void doSomething() {
doAnotherThing();
}
public static doAnotherThing() {
MyClass.myString = "something";
}
}
How is this any different?, and why is writing to a static variable from an instance method a bad practice?, I assume it has to do with synchronization, but it is still not clear to me.
I know this looks like the variable should be final, but I am loading the value from a properties file.
Its a form of aliasing, which may be counter-intuitive. Counter-intuitive code hampers ease of maintenance.
Logically, we expect instance methods to affect that instance's data. We expect static methods to affect static data.
Let's rename doSomething to initialize:
...
a.initialize();
...
b.initialize();
...
The reader of this code may not immediately realize that the instances of a and b are actually affecting the same data. This may be a bug since we're initializing the same memory twice, but its non-obvious since it seems reasonable that we may need to call initialize on each instance.
However, the the code were:
...
MyClass.initialize();
...
MyClass.initialize();
...
In this case, its more intuitive that we're likely affecting the same static data and this is likely a bug.
This is similar to the common version of aliasing where two variables in the same scope point to the same instance.
For your last example,
an instance calls a static method
The fact that an instance method is calling a static method isn't expected to raise flags. The examples were this is useful far outweigh where its likely a problem.
a static method of one class affects another class' static data
In one sense, it should generate a different, but similar warning: that one class is messing with the data of another class. However, by making the static variable public is a way of tacitly approving of this, so such a warning isn't necessary.
Keep in mind that FindBugs is simply trying to flag potential likely problems, not every possible problem, in your code. Your first example is likely a potential maintenance issue that you need to examine whether its a real problem. Your second example is likely not a problem or it is a real problem that is too similar to use cases where it is not a problem.
There aren't many use cases for why you would want to change a static field.
Remember that if you set this field to a new value that this value has changed for all instances of this class.
This might get you into trouble in a multi-threaded environment, where more than one thread is calling doSomething(). Proper synchronisation is required.
In 99% of all cases, you want your instance methods to change the non-static fields only, which is why findbugs warns you.
And findbugs isn't clever enough to find out about your instance method indirectly changing the field in your second example :)
This is what FindBugs has to say about this: http://findbugs.sourceforge.net/bugDescriptions.html#ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD
This is my take, so take it with a grain of salt. You mentioned synchronization issues, which are a major reason for this warning, but more importantly, the two cases are fundamentally operating on different conceptual "levels" of data. Instance methods are "owned" by objects and modify data that describes individual instances. Class methods are generic operations and state that, while related to the class, are not related to individual objects. Thus, modifying that state from within each instance would probably (but not necessarily) be a poor design decision.
Because changing a static field changes it for all instances, causing untold problems if not properly synchronised.
If you're reading in a properties file to set shared fields, then do it in a static method. Alternatively, refactor the fields into a separate singleton instance that the other class can only read from. If you're only going to have one instance, then use a singleton pattern and make the fields non-static.
Static methods should only affect static data, and instance methods should only affect instance data.
I don't think synchronization (mentioned in several answers) has any bearing on this. After all, static methods can be called from multiple threads just as easily as can instance methods.
The reason for the warning (not very well explained by the FindBugs documentation) is, I think, hinted at by a couple of answers: it's suspicious and possibly a mistake. Like Jochen Bedersdorfer said, there aren't all that many use cases where you want to assign to a static variable in one class from an instance method in another. Just like
while (x = y) {
// ...
}
isn't technically an error (and actually legal Java if x and y are boolean), it's almost always a mistake. Similarly, the authors of FindBug felt the same about the subject case.

Constant Parameter Design

I am working with a Class that contains constants or parameter values that all classes can reference for example;
public class Parameters {
public static final String JUMP_TO_VALUE = "Parameters.JUMP_TO_VALUE";
public static final String EXCEPTION_ID = "Parameters.EXCEPTION_ID";
}
Some of the foundation classes in my application will use the parameter values in the Parameters class like so:
mapOfValues.put( Parameters.JUMP_TO_VALUE, "some_value")
This is simple enough I have some basic values in Parameters that most of my base classes will use them. There will be many situations where I will need to add addition parameters to the Parameters class, but I don't want to over populate or pollute the Parameters class ever time a new parameter is identified. I would rather create some subclass of Parameters like:
public class NetworkParameters extends Parameters {
public static final String HOST_NAME = "NetworkParameters.HOST_NAME";
public static final String POST_NUM = "NetworkParameters.PORT_NUM";
}
Some of my specific classes will use the values that are contained in this class versus putting them in the Parameters class.
These specific classes that need HOST_NAME for example I don't want them to reference the NetworkParameters class but rather the Parameters class.
I am sure people have done this before but I am looking for advice on how best to implement this design.
It is simply not possible, in the exact way you describe it.
When you reference static objects, you refer to the class that those objects are declared in. Quite simply, if you declare a constant in the NetworkParameters class, it does not exist in the Parameters class and is not accessible as such.
Separating vast numbers of parameters into different containing classes (which don't need to be subtypes of each other as this achieves nothing) is quite good practice and often used. Why do you have such an aversion to just using NetworkParameters.POST_NUM, as this is the name of the parameter and sounds completely sensible to me?
One thing that may help you (depending on your own tastes) is to use Java 5's static import feature. If, at the top of a class file, you declare
import static the.package.name.Parameters.*;
import static other.package.NetworkParameters.*;
then you will be able to use all of the constant names from both classes without any prefix at all. This is often quite nice when it's obvious what comes from where - but it can become a nightmare if you're statically importing from a few classes, especially if you don't have an IDE to work out the reference for you.
But again - why do you want to reference them as Parameters.FOO, but want them to live in a separate class? Either approach (everything in one file, different constants in different files) is good and fine if you do it completely, but you can't magically change the laws of Java references because you don't like the look of them. :-)
I don't think you would be overdoing it by putting a lot of constants in a single file. Just keep it well organized with good formatting and documentation. I dont think subclassing is want here. A subclass implies a certain relationship among objects. First off, you aren't really creating an object, so creating a subclass does not really fit the model here. Also, using a subclass here may just complicate things. For example, you will have to import multiple java files if you want to use several types of constants in another class.
Are you sure you want to be embedding these values in your code?
They sound to me like the kind of data you want to place in a configuration file, so they can be change easily without the code needing to be recompiled. A simple hash of name-value pairs from a configuration file, wrapped to be accessible in the way you need them to, might be a more flexible approach to the same problem.

Why no global variables in java like C++?

Why there are no global variables in java? If I like to use any variable in all classes of a program then how can I do that?
If you really want to do that, make it a public static variable.
However, you'd be advised to try not to - it makes for less elegant, harder to maintain, harder to test code.
Global variables (in the Java context - public static variables) are bad, because:
harder to maintain - you can't put a breakpoint or log each change to a variable, hence unexpected values at runtime will be very hard to track and fix
harder to test - read Miško Havery's post
harder to read - when someone sees the code he'll wonder:
where does this come from?
where else it is read?
where else it is modified?
how can I know what's its current value?
where is it documented?
To make one clarification that seems needed - variables != constants. Variables change, and that's the problem. So having a public static final int DAYS_IN_WEEK = 7 is perfectly fine - no one can change it.
Some valid global "variables" are constants ;-) for example: Math.PI
C++ is multi-paradigm, whereas Java is pure "almost exclusively"
an object orientated. Object orientated means that every piece of data must be inside of an object.
Please see the links for more information.
Why globals are evil, explained here.
If you need a certain resource that is accessed from any part of your program, have a look at the Singleton Design Pattern.
I just wanted to add that if you want to use a constant global variable its safe. To use it use the final keyword. Example:
public static final int variable;
Global variables do not jive well with OOP. Still one can have constants as global variables. In a sense, singleton are global variables. If you want to have constants as global variables it is better to use enums in stead.
EDIT:
Constants which used to invoked as Class.Constant now can used Constant by using static import. This comes as close as possible to global variables in C++.
package foo;
public class Globals {
public static int count = 3;
}
Then, you can access it anywhere as
int uses_global = foo.Globals.count + 1;
Java is intended to make fully-portable, fully-reusable objects.
By definition, something that depends on a "global variable" is not fully portable or fully reusable. It depends on that global variable existing on the new (reusing) system, and it depends on code on the new (reusing) system manipulating that global variable. At that point, you're better off putting that global variable into an object of its own.

Categories