5

I recently came across some code where a public static method was defined inside an abstract class. I am wondering whether this is considered good practice or an anti-pattern?

I've produced a simple example program to illustrate what I mean.

public abstract class StaticMethodsInAbstractClassesStudy {

    public static int adder(int a, int b){
        return a + b;
    }

}

public class StaticMethodsInClassesStudy {

    public static void main(String [] args){

        System.out.println(StaticMethodsInAbstractClassesStudy.adder(2, 3));

    }
}

When you run the code you get the result of 5 which proves that I was able to run code inside of an abstract class.

I've deliberately not added extends to StaticMethodsInClassesStudy to emphasise the point that it's perfectly possible to run code directly inside an abstract class without instantiating an extending class.

Personally I would have thought that this is bad practice since you're using an abstract class as a normal Class and thereby bypassing the intent of abstract classes. Shouldn't these kinds of methods be kept in separate "normal" java classes e.g. utility classes ?

robbie70
  • 1,515
  • 4
  • 21
  • 30
  • If you never intend `StaticMethodsInAbstractClassesStudy` to be instantiated (that is, there is no use for an instance of `StaticMethodsInAbstractClassesStudy`), there is no reason for it to be abstract. Make it a final class with a private constructor. – Andy Turner Oct 10 '19 at 13:20
  • 1
    Please define "good practice" and "bad practice". These are just opinions. – jaco0646 Oct 10 '19 at 13:20
  • it really depends on the method involved, static is generally abused by people first getting into programming as a bandaid for field/method access. In general, as long as the static method is being used in a way that isn't going to modify some internal (and static) state, it's generally fine to be static. Overall it comes down to what you're designing – Rogue Oct 10 '19 at 13:22
  • 1
    Another thing to consider: `static` methods are not inherited and therefore cannot be overridden by a subclass. If you intend for it to be overridden then it cannot be `static`, if you don't want it to be overridden, then `final` does that for you more explicitly than `static` does. – JonK Oct 10 '19 at 13:22
  • Of course you can run code in abstract classes. You just can't instantiate them. A static initializer would be another way to demonstrate it, without subclassing or otherwise messing with your example. – Kayaman Oct 10 '19 at 13:26
  • Some (or even many) people consider things that are involving `static` as something "bad". **It is not**. (Complaints about `java.lang.Math` anyone?). A static method is inherently state-free, and thus, purely functional (and if it is not, that is, when there are static fields involved, then yeah, that's nearly always cr4p...). Having a `public static` method in an `abstract` class is somehow unusual, but there may still be cases where it is justified. Related, referring to `protected abstract`: https://stackoverflow.com/q/24289070/3182664 – Marco13 Oct 10 '19 at 16:00

2 Answers2

2

It's not bad practice per se, unless the abstract class is actually not meant to be subclassed, and abstract is only there to prevent instantiation. The best practice for a class providing only static utilities would be to make it final, and to have a private constructor.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • "The best practice for a class providing only static utilities would be to make it final, and to have a private constructor." > a convenient way to do this is to make an enum without instances. – bowmore Oct 10 '19 at 13:26
  • @bowmore and that, IMHO, would be just as abusive (if not even more) as using an abstract class to prevent instantiation. An enum is supposed to have enum values. it has a valueOf() method, a values() method, etc. that are not supposed to be part of a utility class. – JB Nizet Oct 10 '19 at 17:29
  • Well, I'd say making a class providing only static utilities, you're already throwing best practices out the window :) – bowmore Oct 10 '19 at 22:32
  • @bowmore huh. No. It's quite common and normal to have static utility and factory methods. See java.util.Collections, SwingUtilities, Guava's Maps, Lists, Sets, etc. – JB Nizet Oct 10 '19 at 22:36
  • Being commonly used does not indicate best practice though. Factory methods are of course a great use of static methods, but I fail to see why these need to be grouped in a separate class that cannot be instantiated. Other types of static methods, housed on a non instantiably class, just promotes strong coupling. Essentially it suffers from much of the same problems of the singleton. Also, looking at `Collections` for instance, you see a lot of methods like max, reverse, rotate, shuffle, etc. that clearly smell of feature envy. The same goes for SwingUtilities. – bowmore Oct 11 '19 at 06:56
  • @JBNizet thanks for your answer - when you say "The best practice for a class providing only static utilities would be to make it final, and to have a private constructor" would you not add that this should be in a normal Class and not an Abstract class ? surely it cant be right to be able to run methods inside an Abstract class when the intent of an Abstract class is that it is not "instantiable" and so should only be inherited from. Infact I might go as far as to suggest that this is a flaw in the language that this is even possible. – robbie70 Oct 11 '19 at 09:51
  • Maybe that's not clear enough: the class should definitely not be abstract. If it's final, as I suggest, it can't be: that wouldn't compile. An abstract class may not be final. – JB Nizet Oct 11 '19 at 10:42
  • @JBNizet thank you for the clarification I will mark yours as the answer. The moderator has maintained the hold status on this question which I find a bit frustrating - surely unless the development community has an opportunity to discuss and then vote and so converge around an answer I don't know how we're supposed to get at best (vs worst) practice in our profession. Maybe I need to see if I can re-phrase the question to more conform to the SO format. – robbie70 Oct 11 '19 at 15:43
  • @JBNizet the creator of the enum class for java would disagree with you on this one (Bloch) – Rogue Oct 14 '19 at 02:55
  • @Rogue Err, I don't think so: https://books.google.fr/books?id=BIpDDwAAQBAJ&printsec=frontcover&dq=joshua+bloch+effective+java+item+4&hl=fr&sa=X&ved=0ahUKEwjNyKeOjpvlAhWs4YUKHeZpBxsQ6AEIKzAA#v=onepage&q=joshua%20bloch%20effective%20java%20item%204&f=false (scroll until "Item 4") – JB Nizet Oct 14 '19 at 06:23
  • Item 3 before that, I'll give you that it's for singletons (not static utilities), but: `a single-element enum type is often the best way to implement a singleton`. Last few sentences – Rogue Oct 14 '19 at 18:01
0

I agree with you that a abstract class make us think of something to not use until it will be instantiated.

It's allowed and useful to insert some support methods inside an abstract class without enforce the developer to implement that class.

Also in an Interface you can put static methods, and you can use them without implementing that interface.

user2342558
  • 5,567
  • 5
  • 33
  • 54