0

As per Item 19 in Effective Java, one must use an interface to only represent a type. In this case the interface would contain the methods that form part of the public contract that is exposed by a class (implementing the interface) to the clients

If so, why do interfaces support fields in the first place? Since the fields are implicitly public, static, final, (and hence constants), why did the language designers support having them? If they were unsupported then developers would invariably use utils class (with private constructor) to define these constants. The anti pattern of using constants only interfaces could have been automatically avoided

I am looking at understanding the reasons for supporting constants in the interface. Are they essential as part of the contract with the client?

Thanks

Sirish Renukumar
  • 1,509
  • 2
  • 13
  • 16
  • 1
    *" If they were unsupported then developers would invariably use utils class (with private constructor) to define these constants."* Which is also very ugly. – Tom Dec 20 '15 at 02:00
  • 5
    Err, because Java was designed long before the book came out? And because *Effective Java* isn't a language specification, only a set of recommendations of varying quality? – user207421 Dec 20 '15 at 02:16
  • @Tom, Possibly. But atleast the contract exposed by the interface would not be dirty in a sense and contain constants that don't indicate any behavior of the type. – Sirish Renukumar Dec 20 '15 at 02:18
  • 1
    Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. – Krease Dec 20 '15 at 02:22
  • Language constructs stem almost always from some creative idea, and then later are tested in practice. Interfaces were introduced to do away with multiple inheritance. They look like algebraic types, and those types often have discriminating constants like HOR/VERT, R/G/B, MAX:STACK_SIZE (better a type param). So starting _without_ constants would need a not yet possible insight, that interface might do better without them. – Joop Eggen Dec 20 '15 at 02:23

2 Answers2

1

One reason might be constants which are essential to the interface's contract. For instance, consider the following interface:

/**
* Generates a probability distribution on a
* specified interval.
*/
public interface DistributionGenerator{
    /*
    * Gets a probability distribution on the specified
    * interval. The exact distribution is unique to the 
    * implementor of this interface. The distribution will
    * be represented as an array of doubles. The first number
    * in the returned array will be the probability at start
    * The last number will be the probability at end. All numbers
    * in between will be probabilities at evenly spaced 
    * intervals between start and end, with the spacing between values
    * given by the constant INTERVAL
    */
    public double[] getDistribution(double start,double end);

    public static final double INTERVAL = 0.000001;
}

However, as you observed, most of the time you see constants in interfaces it is done to simply expose the constants for their own sake, and this is generally considered bad practice.

Community
  • 1
  • 1
augray
  • 3,043
  • 1
  • 17
  • 30
1

Are they essential as part of the contract with the client?

They are if the constant can be given as a parameter to one or more of the interface methods, or if the constant is a documented special return value of one or more of the interface methods.

The use of an interface to hold constants for easy use by a class is an anti-pattern, and there are many articles about that, but it is valid to have constants that are specifically for use by the methods defined in the interface itself.

However, using enum types and the new Java 8 Optional will eliminate most use-cases for such special constants, so they are very rarely seen in real life.


As an example, the InputStream.read() methods all return -1 for "end of the stream". Sure, it is well documented, but wouldn't use of the methods be better self-documented if InputStream had defined a END_OF_STREAM constant for -1?

while ((len = inputStream.read(bytes)) != InputStream.END_OF_STREAM) {

// or using a static import:
while ((len = inputStream.read(bytes)) != END_OF_STREAM) {

Ok, well, InputStream is an abstract class, not an interface, though it should have been, so not a perfect example, but it illustrates the point I was trying to make.

Andreas
  • 154,647
  • 11
  • 152
  • 247