I have an encryption utility method that relies on an external dependency --- a cipher key which is being retrieved from a property file. The way it can be retrieved in the current code base which I inherited is that it relies on creating new objects to be able to get the value of a property in the properties file. For example, if wanted to get the Cipher Key from the property file, it would be like this:
public synchronized static String encrypt(String someTextToEncrypt) {
String propertyValue = null;
propertyValue = getProcessCommonBase().
getProcessProperties.getProperty("CIPHER_KEY");
/*encrypt algorithm*/
return encryptedForm;
}
private synchronized static ProcessCommonBase getProcessCommonBase() {
if (processCommonBase == null) {
processCommonBase = new ProcessCommonBase();
}
return processCommonBase;
}
private static ProcessCommonBase processCommonBase;
EDITED: Design-wise is having a something like the processCommonBase instance variable a good practice to do? My understanding is that a good practice is that static variables should be final and do not change. In this case, however, the ProcessCommonBase class maintains state and is subject to change.
NEW QUESTION: If the static method relies on something external shouldn't I just mark the method and the processCommon base variable as non static and in Spring, just make a bean definition for it? What is better?
I agree with Joonas. I don't see why not make the variable final. Could you elaborate please what exactly do you mean by this:
My understanding is that a good practice is that static variables should be final and do not change. In this case, however, the ProcessCommonBase class maintains state and is subject to change.
Even if the variable is final, you still can change the object it references to in exactly the same ways as you'd do it with a non-final variable. That's why it's perfectly fine for a static method to have a static variable maintaining its state, but nothing stops you from actually making it final in this case. Why not do this:
private static ProcessCommonBase processCommonBase = new ProcessCommonBase();
Maybe there's something stopping you from creating processCommonBase at static initialization time, but it isn't obvious from the information you have provided.
Someone already commented your specific case, but in general, what you described is an effectively final static variable, which is just created "lazily" (that is, only when needed). It's a fine approach, if creating a ProcessCommonBase instance is an expensive and rare event, although you must be careful to access it only via the getter method then. On the other hand, if a ProcessCommonBase will be created whenever the surrounding class is used, then making it actually final is a better approach: it's simpler (less error prone, as you don't need to remember to use the getter method exclusively), and will actually be a bit cheaper, as the final variable is initialized only when the surrounding class is first used, and you don't need the (synchronized!) null check every time when accessing it (of course, if you use > 1 threads andProcessCommonBase isn't thread-safe, then you need to synchronize somewhere).
Answer to your second question: being static vs. not and relying on some external system properties are two separate things. I don't know what Spring does, but if your method essentially a function - "value in, result out" - then it's a static method by its nature, even if it reads its configuration from some system property. Making such methods instance methods is possible, but if it only complicates things and gives nothing, why bother?
The usage of static is often frowned upon from an OO design perspective because it gives tight coupling between objects. With statics methods it’s impossible to decouple an interface from its actual implementation. This lack of decoupling can for example become a problem when you want to unit test a single class, as it can’t be separated from the other static parts.
In today’s Java landscape you’re singleton crypt class can be much better designed with the help of Dependency Injection (DI). The ProcessCommonBase could also be implemented as an DI singleton if it didn’t had that very strong code smell, because if it’s a god-object then it should be refactored, for example by using DI for injecting properties into you crypt class.
Example code based on Google Guice:
#Singleton
public MyCrypt {
private final key;
#Inject
MyCrypt(#CipherKey String key) {
this.pBase = pBase;
}
public synchronized String encrypt(String someTextToEncrypt) {
/*encrypt algorithm*/
return encryptedForm;
}
}
Configuring DI properties:
public class PropertiesModule extends AbstractModule {
#Override
protected void configure() {
String key = .. what ever ..
bind(String.class).annotatedWith(CiperKey.class).toInstance(key);
}
More DI examples can be found here:
http://java.dzone.com/articles/cdi-overview-part-1
Populair Java DI implementations are: Guice, Spring and Java EE6.
Related
I am creating an application in Java which performs data movement task (like copy, move, etc.)
At the higher level, I can provide these operations on object level.
Sample code:
public class DataSource {
public boolean copy(DataSource dsDestination);
public boolean copy(DataSource dsDestination, Filter filter);
public boolean move(DataSource dsDestination);
public boolean exists();
// some other 10-15 methods
}
Or I can provide a utility with static methods:
public class DataSourceUtil {
public static boolean copy(DataSource dsSource, DataSource dsDestination);
public static boolean copy(DataSource dsSource, DataSource dsDestination, Filter filter);
public static boolean move(DataSource dsSource, DataSource dsDestination);
public static boolean exists(DataSource dsSource);
// some other 10-15 methods
}
Which one is better approach in terms of memory management?
The golden rule is: static is an abnormality within good OO design. You only use it if there are good reasons to do so.
You see, static leads to direct coupling between your classes. And it makes testing harder. Of course, the static methods themselves can be easily tested, but what would happen if you want to test a method that calls those static methods (and you have the need to influence what the static method is doing)? Then you might be tempted to turn to Powermock in order to mock those static calls. Which is not really a great idea.
If you insist on separating functionality, you better use interfaces, like:
public class DataSource {
... ctor, equals, ... methods
}
public interface DataSourceCopyAbility {
public void copy(DataSource source, DataSource destintion);
plus corresponding impl class.
EDIT: of course, convenience can be a valid reason to use static methods; for example I am using Objects.requireNonNull() all the time in code. But: those are standard API calls. When I am using them in my code, I really dont mind them to be running. I know that will never ever want to "mock" around such kind of static method invocations!
Finally: I assume you want to return true when your operations passed. Bad idea: booleans should only be used to distinguish between true and false. They are not return codes!
If such a complex operation as copying a DataSource fails - then throw an exception! Or if you really want to go without exceptions, define your own specific ReturnCode class that gives you insight into failing operations!
Forget about memory management.
No matter which method you use, you are still going to create two DataSource objects to call copy or move. There is little difference in memory usage.
What you should focus on instead, is readability and aesthetics :).
Compare these two:
someData.copy(otherData);
DataSourceUtils.copy(someData, otherData);
The second one is more verbose. Also, it seems that we need some other stuff (DataSourceUtils) to help with copying data. It would be less code to write and make more sense if we let the data copy itself (first one).
Another point that I want to point out is that you can add a To in the first one to make it a lot more readable:
someData.copyTo(otherData);
You can't do this with the second method.
I agree with #Jon Skeet , as all the operations need source object which is Datasource itself, then they should be instance methods. They are similar to equals in Object class.
From testable point-of-view instance methods are easy to test.
It depends on the functionality that you are writing in these methods..If the functionality is not using any object specific field values then using static methods would be the correct option.
i.e. make sure the variable information that you are using is not specific to object and data is common to class level
Memory management point of view, by the way, they are equivalent. The functions are share their compiled codes which is stored into the read only memory area. Only the difference between those two are the this pointer context. So it should not occupy any more space if you choose static or non static. Most of the compiled languages are following same manner.
the difference:
dataSource.copy();
copy is not my responsibility and it is a responsibility of DataSource.
DataSourceUtil.copy();
copy is my responsibility,but source code has been written in a utility class to avoid duplication.
Drawing from the experience of Apache Commons Lang library and java.lang.Objects, the advantage of static methods is that they can provide protection from NullPointerException
It is quite common to see something like this in Java code:
if (x != null && a.equals(otherX)) ...
or the practice of putting the literal on the left side:
if ("literal".equals(str)) ...
These are all NPE-protection ways. This is one of the reasons for the abovementioned liberary, and the case for static methods:
if (ds.copy(dest) == true) ... // may throw NPE
if (DataSourceUtil.copy(ds, dest) == true) ... // NPE protection
I have an Enum class that requires a function object (in this case, one of Guava's StringConverters) to initialize one of the fields. It could look like this:
private MyEnum(String input) {
this.myField = someFunctionObject.convert(input);
}
However, once all the members of the enum are finished loading, I have no use for this object. What's the best practice for handling this? It seems my options are:
Have a private static object somewhere that persists after the enum is finished initializing, creating a pseudo-memory leak. (I could also null it out when I'm done, but then I still have a useless static reference which still is ugly.)
Create and re-create the object each time the enum constructor is called.
Make the field non-final and use a static initializer block that only needs to create the function object once, then loops over the enums and initializes the fields outside of the constructor.
It's not like this is a big deal, but this process has come up a few times, and I don't like any of these solutions. I don't think this is an issue of premature micro-optimization, either, it's an issue of the most elegant/ readable/ sensible way to perform this.
I think a variation on option 2 would be fine, since the constructors are only called X times for an enum of X values.
Static initializers are very ugly and instantly raise the warning flag whenever I see them. A static object that is later nulled is similarly not so elegant either.
If you can live with a factory call, all of the "static awfulness" can be confined to a factory class.
private MyEnum(String input) {
this.myField = SomeFunctionFactory.getInstance().convert(input);
}
Please also see here, there is a way to do this via dependency injection frameworks:
Inject bean into enum
I was prefer using static methods in my java code, since I think they are "functional""stateless" and has less side-effect. So there may be some helper classes and methods like this:
public class MyHelper {
public static Set<String> array2set(String[] items) { ... }
public static List<String> array2list(String[] items) { ...}
public static String getContentOfUrl(String url) {
// visit the url, and return the content of response
}
}
public class MyApp {
public void doSomething() {
String[] myarray = new String[]{ "aa","bb"};
Set<String> set = MyHelper.array2set(myarray);
String content = MyHelper.getContentOfUrl("http://google.com");
}
}
But my friend says we should avoid defining such static utility methods, since we call them directly in our code, it will be hard to mock them or test them if they have external dependencies. He thinks the code should be:
public class ArrayHelper {
public Set<String> array2set(String[] items) { ... }
public List<String> array2list(String[] items) { ...}
}
public class UrlHelper {
public String getContentOfUrl(String url) {
// visit the url, and return the content of response
}
}
public class MyApp {
private final ArrayHelper arrayHelper;
private final UrlHelper urlHelper;
public MyApp(ArrayHelper arrayHelper, UrlHelper urlHelper) {
this.arrayHelper = arrayHelper;
this.urlHelper = urlHelper;
}
public void doSomething() {
String[] myarray = new String[]{ "aa","bb"};
Set<String> set = arrayHelper.array2set(myarray);
String content = urlHelper.getContentOfUrl("http://google.com");
}
}
In this way, if we want to write unit tests for MyApp, we can just mock the ArrayHelper and UrlHelper and pass them to the constructor of MyApp.
I agree totally about the UrlHelper part of his opinion, since the origin static code make MyApp untestable.
But I have a little confused about the ArrayHelper part, since it doesn't depend on any external resources and the logic will be very simple. Shall we avoid using static methods at this case too?
And when to use static methods? Or just avoid using it as much as possible?
update:
We are using "TDD" in our development, so the testability of a class often is the most important concern for us.
And I just replace the word "functional" with "stateless" in the first sentence since the that's real what I meant.
You'll probably never want to mock a method that converts an array to a list (or set), and this method doesn't need any state and doesn't depend on any environment, so a static method looks fine to me.
Just like the standard Arrays.asList() (which you should probably use).
On the other hand, accessing an external URL is typically the sort of thing that you want to be able to mock easily, because not mocking it would
make the test an integration test
require to have this external URL up every time you run your tests, which you probably can't guarantee
require to have this external URL return exactly what you want it to return in your test (including errors if you want to test the event of an error).
Just beware of one disease very common amongst Java "experts": overengineering.
In your specific example, you either do or don't have a mockability issue. If you had an issue, you wouldn't be asking general questions, therefore I conclude you don't have an issue at the moment.
The general argument is that static methods are simpler and therefore the preferred choice, whenever there is a choice. A would-be instance method must first prove itself of needing to be an instance method.
If this was my project, I would defer any makeovers into instance methods until such a moment where the need for that became clear and present.
Static means you can call the method without instantiating the class. Its good if you want to package your code into a class and you have a function that just does some logic or something basic.
Just don't use a static function to try and edit member variables in the class (obviously).
Personally I think its fine to use the static function, since it is stateless.
Static methods should be used by answering the question "is this method a functionality of a specific instance?".
You shouldn't decide about a static method according to tests, you should do it according to design. Your examples doesn't need an instance because it makes no sense. So static is the better choice. You can always wrap these methods inside specific tester classes to do your tests.
The only situation in which a self-contained functionality is not static is just when you want to provide multiple implementation, so that you are forced to avoid static because you need inheritance.
I often use static methods:
for factory methods (explicitly named constructors)
to provide a functional layer above an object-oriented layer, to compose the objects
and sometimes for general-purpose functions (Apache Commons has many good examples of this)
I never use "singletons" (static objects) and methods that refer to static objects because they are a complete headache to test and reuse. I also avoid hardcoding anything into a static method that could feasibly need to be changed. Sometimes I will provide multiple methods - one with all the dependencies as parameters and others, with fewer parameters, that call the more flexible method with some default (hardcoded) values.
java.lang.Math is static which is a good example. I thought statics are not beeing garbage collected and should be avoided if possible.
No.
As mentioned by Peter Lawrey in the comment for the question, Java is all about object oriented programming. While certain functional aspects are doable and being put into eg. Java 8, at its core Java is not functional. static breaks so much of the benefits of learning how to do modern Java - not to mention all kinds of not-fun-at-all scoping problems - that there's no purpose to use them unless you're some kind of a Java wizard who really knows what happens when you use that magical keyword.
You are not a wizard. Java is not functional. If you want to be a wizard, you can learn. If you want to program in functional fashion, look into hybrid languages such as Scala or Groovy or alternatively explore the fully functional world, eg. Clojure.
I have a singleton class.
When accessing the methods of the class I have the choice of two possibilities.
Create those methods as instance specific and then get the instance and invoke them
Create those methods as static and invoke them and they will get the instance
For example:
Class Test{
private int field1;
Test instance;
private Test(){};
private Test getInstance(){
if (instance == null)
instance = new Test();
return instance;
}
public int method1() { return field1;}
public static int method2() {return getInstance().field1;}
}
Now, elsewhere I can write
int x = Test.getInstance().method1();
int y = Test.method2();
Which is better?
I can think of a 3rd alternative where I use "instance" directly in the static method and then capture the exception if it is null and instantiate it and then re-invoke itself.
I could, in theory, just make the whole lot static.
However, this will create me problems when saving the state at activity close since the serialization doesn't save static.
I think the first one is cleaner.
However, keep in mind that under some extreme cases, Android may kill your static instances. See this for example: http://code.google.com/p/acra/ .
A workaround I've found somewhere for this, is to keep a reference to your singleton from the Application class, as well. I don't know how problem-proof this is, though.
You should avoid making everything static. Some people would even say that a singleton is not done.
The whole point of the singleton pattern is that you can change the implementation. In most cases you use it to keep the possibility open to "hook" in some other implementations of this functionality later.
Read: when deciding in favor of singleton plan for a setInstance method too, not just for a getInstance. - If this does not make sense, just use a plain static class.
In the other hand singletons are out of season, if you want to be hip and all that. Do a search for "eliminating global state". There are some Google-sponsored talks about it too. In short: your code will be more testable and helps you avoid some dependency chaos. (Besides being hip and all, it is definitely a step into the right direction).
In my personal opinion having static methods is bad design in the first place. It, of course, depends on the program itself, but allowing a class to have static method will have impact on the whole design. Some reasoning behind my statement:
If static method can easily change state of some object, sooner or later bugs will emerge
If you publish static method with your program, every client that will use it will have a very strong dependency on your code. If you decide to remove or change this method someday - you will break every single client that used your class.
So, if you can - avoid it.
If, from any reason, you will insist on having static method, I guess the first solution is better. That's how singleton should work. You should obtain a reference to a SINGLETON OBJECT via static method, but this object should be then used according to all principles from Object Oriented Programming.
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.