Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending non-instantiable class in java

Tags:

java

I read "Effective Java" by Joshua Bloch and removed the 'Constant Interface anti-pattern' from our application. The trick is to use Non-instantiable util class whose constructor is private, and define all the constants as 'public static final'

I have to extend the this constant util class. I can only do this when I change the constructor to protected.

Could somebody suggest a better way.

public class Constants {
    private Constants () {} // Prevent instantiation
    public static final String MyString = "MyString";
}

public class MyConstants extends Constants {
    private MyConstants () {} // Compiler error : Implicit super constructor Constants() is not visible.
    public static final String MySecondString = "MySecondString";
}
like image 562
Nayn Avatar asked Jan 09 '10 12:01

Nayn


4 Answers

You are not typically supposed to extend these constant classes. Could you provide us with a more concrete example of what you're trying to do?

Typically you'd want to group constants together when they are related, e.g., maths constants or configuration parameter names for a particular functional component.

If the constants are really related, is there anyway you could just add them to the original class? Alternatively, is there any reason you can't create a separate class for your constants?

like image 96
Jack Leow Avatar answered Nov 13 '22 01:11

Jack Leow


I usually do the following:

public abstract class Constants {
    // ...constants...
    public Constants () {
        throw new UnsupportedOperationException();  // prevent instantiation
    }
}

This way the class can be extended to create a derived utility class, but any (misguided) attempt to instantiate it will fail. I wish java.util.Collections was defined that way, so one wouldn't have to define a Collections2 (or similar) for additional utility methods.

BTW, given an abstract class, "protected" and "public" effectively mean the same for constructors. There's practically no benefit in just making a constructor protected, as anyone can still easily create an instance of the class despite the "protection":

public class Base {
    protected Base() { }
}

// Somewhere else:
Base b = new Base() { };  // anonymous subclass
like image 32
nmatt Avatar answered Nov 13 '22 02:11

nmatt


I don't see anything wrong with changing the constructor to protected.

I also don't see anything wrong with using interfaces to hold constants.

like image 26
Carl Smotricz Avatar answered Nov 13 '22 00:11

Carl Smotricz


If the classes are in the same package and you want to forbid inheritance for non-package classes, consider using default access:

public class Constants {
    Constants () {} // Prevent instantiation
    public static final String MyString = "MyString";
}
like image 44
McDowell Avatar answered Nov 13 '22 02:11

McDowell