Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
What are the disadvantages of using static methods in Java?
I was using static method few moments ago. But I noticed that I was returning a variable using that static method. According to the article,
Static is a keyword that identifies the class-related thing. It means the given Method or variable is not instance-related but Class related. It can be accessed without creating the instance of a Class.
I think I can access the static method without caring of class, isn't it? Is there something special of static method? static method can helps to decrease amount of source code. So Is it better to use static method? Or is there any limit of it?
4 answers
I am not a Java developer, but a C# .NET one, but I guess static concept is very similar between the two.
As in many areas, it depends, but for most applications using static should be avoided:
- Single Responsibility Principle violation
- prevents polymorphism
- prevents abstraction (cannot use in an interface)
- prevents inheritance
- makes automatic testing through mocking way more complex and tedious
- prevents garbage collector to kick in and collect the memory
For the specific case of utility functions, static is very useful, but for a medium or large application, this is only a tiny part of the codebase.
0 comment threads
Is it better to use static method?
I don't like to think of static
(or any other language feature/mechanism) in terms of bad/worse and good/better (although I do that too, I constantly try to avoid it).
What I usually try/prefer to do is to understand how something works, why it exists, the pros and cons of using it, and then decide when it does or doesn't make sense to use it (for the so-called "OO languages", my understanding is that "many" times static
is not the proper solution, but my answer to questions like this is usually "it depends").
The other answers are - correctly - pointing situations where static
doesn't apply, either because it's not the best option (prevents polymorphism, inheritance, etc), or because it's the wrong mechanism to use (a static
method can't access instance fields, so you can't "do OOP" at all). I'm not repeating all their explanation and examples (just mention some of them when pertinent).
The point of this answer is to claim that static
is not "evil". It has its uses, and the most important thing IMO is to understand how it works and when to use (or avoid) it.
Obviously if you want to "do OOP" (access instance variables/methods), you can't use static
, as the other answers explained. But in this case, it's more than a simple recomendation: it's a constraint imposed by the way the language works. If you declare any stuff static
, it won't be an instance's stuff. If you want to "go OOP", you have no choice: those stuff must not be static
.
But what if that stuff is not related to any instance at all? It's not uncommon to have private auxiliary methods that do some specific task not related to an instance. BTW, we can find lots of examples in the JDK source code. Ex: in java.time.LocalDate
class, the current implementation of withYear
method (which is an instance method) calls the resolvePreviousValid
method:
public LocalDate withYear(int year) {
if (this.year == year) {
return this;
}
YEAR.checkValidValue(year);
return resolvePreviousValid(year, month, day);
}
But the resolvePreviousValid
method is static
: it does some stuff with the year
, month
and day
values, but those stuff don't depend on any instance state, and the method was made static
. I don't know who decided that, or why this was made, but IMO it makes clear (for anyone who'll have to read and/or maintain this code) that this method doesn't rely on instance fields and I don't see a big problem with it being static
. Of course it has the cons mentioned in another answer (static
reduces testability, etc), but it's a private
method, and therefore not good a candidate for automated tests.
Could the resolvePreviousValid
method be non-static? Of course it could, and I admit that in this case it doesn't make much difference: the LocalDate
class is final
after all (it can't be extended), so the "static
prevents inheritance" argument doesn't apply here as well, therefore it seems to be a matter of "style": they make it clear that the method doesn't depend on any specific instance, sacrificing testability, inheritability and other stuff that probably they didn't think of as a priority for this method (to me, a fair trade-off).
Another example found in the JDK is the java.lang.Math
class. It has no public constructor, and all the public methods are static
. IMO, it makes sense, because this class has no internal state (what fields would a Math
instance have?) and all the mathematical functions (such as abs
, floor
, sqrt
, etc) simply perform some operations/calculations that are independent of any internal state, thus having an instance is not necessary.
Would it be worth to require an instance to be created? Such as:
Math m = new Math(); // Would it make sense to be like this?
double result = m.sqrt(x);
double f = m.floor(result);
I don't think so. Why create a Math
instance, when Math.sqrt(x)
and Math.floor(x)
would do the job? Considering that all these methods are "self-contained" and don't depend on any internal state of the Math
instance (if such instance were created), I don't think they should be made non-static just for the sake of "best practices"[1], or because "this is not OOP"[2].
One could also argue that utility classes (such as StringUtils
, DateUtils
, WhateverUtils
, that I've seen in basically all projects I've worked on) have static methods due to the language's "limitations": everything must be inside a class and you can't change native classes.
For example, in Ruby and JavaScript you can add methods to existing classes (even native ones). Example in JavaScript:
String.prototype.whatever = function(...args) {
// do whatever you want with args
// use "this" to refer to the string instance
}
// use the newly created method on any string
'abc'.whatever(args);
In C# you can create extension methods, which is similar (although not exactly the same, as it's only a syntatic sugar), but they're implemented with... static
methods!
Java doesn't have such features, and the "best" alternative is to create utilitary classes with static methods. Using the JavaScript example above, in Java it'd be like this:
public class StringUtils {
public static String whatever(String s, Object ...args) {
// do something with "s" and args...
return result;
}
}
... // use the class
String result = StringUtils.whatever("abc", 1, 2);
Would it be worth changing this class to require the creation of an instance? Such as:
StringUtils utils = new StringUtils();
String result = utils.whatever("abc", 1, 2);
Unless the whatever
method needs to access the internal state of the StringUtils
instance, there's no benefits in doing so. Just "follow the best practices", or "make correct OO code" (whatever that means, because nobody agrees on what it is) is not enough to justify that, IMHO.
static
is not "evil". You should use when it makes sense (or when there's not a better alternative).
Just to provide another example, consider Static Factory Methods. In Java, you can find many examples in the native API, such as Optional.of
, Calendar.getInstance
, Collections.unmodifiableList
, and so on. All are implemented as static
methods. Could they be implemented in a different way, maybe by having factory classes (such as f = new CollectionsFactory(); f.unmodifiableList()
)? Yes, they could, but I can see the convenience of having those implemented as static
methods.
That's a good use case for static
methods, IMO. Making those non-static would bring little to no benefits (unless you really need testability, inheritance, polymorphism, etc). I'm not saying that static
is always justified, nor that non-static must be avoided. I'm saying that, knowing how static
works, you can make better choices when coding: do you need to access instance fields/methods? So they must be non-static. The method doesn't access any internal state, or it's an utilitary class? It's a good candidate for static
. But I need those to be testable, and/or inheritable, and/or polymorphic. Then make them non-static. No, I don't need those things, and the class is actually final
(can't be subclassed), the method is private
and/or so specific to this class that it won't be used anywhere else. Hence, making them static
won't hurt...
There's no silver bullet, and YMMV.
0 comment threads
I think I can access the static method without caring of class, isn't it?
No. A static method is still a class method, and you still care about the class. The difference is that static methods aren't used with an instance of a class (an object).
static method can helps to decrease amount of source code.
True. As you pointed out in comment (putting it here too for better visibility): import static com.classes.Car.numCars();
means that you can simply invoke it as numCars();
So Is it better to use static method? Or is there any limit of it?
Opinions differ. The main thing is that you can't access object members in a static method, only static members.
For example, you might have a Car
class, with a fuel
member and a drive()
method that makes fuel
go down. You might also have a private static int numCars
member, and a static printNumCars()
method.
When accessing your static method, you still care about the class. It's still going to be Car.numCars()
. numCars()
has no way to access the fuel
member, and that makes sense (which car's fuel would we be talking about?). On the other hand, "how many cars are there" isn't a property of any one specific car at all, it's a property of cars in general, as a whole category.
That's what static members are for - things that are relevant to the entire class, rather than any individual object.
If it were always better to use static
, the language would have been designed to always assume static
, or at least default to static
. That the language defaults to making methods not static indicates that the designers of the programming language envisioned static methods to be rare.
Java is intended to be an object oriented programming language, where a program is a set of objects that "talk" to each other using methods. Objects are created from classes, and classes can be related through inheritance. Specifically, a class can be declared to extend another class, which allows it to inherit or override methods from the parent class. For instance:
class Animal {
void move() {
System.out.prinln("The animal moves");
}
}
class Dog extends Animal {
@Override
void move() {
System.out.println("The dog walks");
}
}
class Snake extends Animal {
@Override
void move() {
System.out.println("The snake slithers");
}
}
Which you can then use as follows:
Animal animal = new Snake();
animal.move(); // "The snake slithers"
So even though the variable contains an Animal
, that Animal
knows whether it is a Dog
or a Snake
, and responds accordingly when it is asked to move
.
This ability to refine the behavior of a class in a subclass is very useful. However, since this depends on the type of the object, it is only available for methods of objects, not static methods.
By using static, you deny yourself this useful tool. This may seem a small price to pay when your programs are tiny and consist only of a few isolated methods. However, once your programs get bigger, and particularly once they start incorporating code written by other people, the ability to refine code they have written will be invaluable.
1 comment thread