Interfaces with Static Fields in Java for Sharing 'Constants'

Interfaces with static fields in java for sharing 'constants'

It's generally considered bad practice. The problem is that the constants are part of the public "interface" (for want of a better word) of the implementing class. This means that the implementing class is publishing all of these values to external classes even when they are only required internally. The constants proliferate throughout the code. An example is the SwingConstants interface in Swing, which is implemented by dozens of classes that all "re-export" all of its constants (even the ones that they don't use) as their own.

But don't just take my word for it, Josh Bloch also says it's bad:

The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.

An enum may be a better approach. Or you could simply put the constants as public static fields in a class that cannot be instantiated. This allows another class to access them without polluting its own API.

What is the use of interface constants?

Putting static members into an interface (and implementing that interface) is a bad practice and there is even a name for it, the Constant Interface Antipattern, see Effective Java, Item 17:

The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.

There are several constant interfaces in the java platform libraries, such as java.io.ObjectStreamConstants. These interfaces should be regarded as anomalies and
should not be emulated.

To avoid some pitfalls of the constant interface (because you can't prevent people from implementing it), a proper class with a private constructor should be preferred (example borrowed from Wikipedia):

public final class Constants {

private Constants() {
// restrict instantiation
}

public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}

And to access the constants without having to fully qualify them (i.e. without having to prefix them with the class name), use a static import (since Java 5):

import static Constants.PLANCK_CONSTANT;
import static Constants.PI;

public class Calculations {

public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}

Interface can have only static variables in JAVA?

Yes, because interfaces cannot be instantiated, so instance state would not make sense.

A quick Google search found the same answer.

http://www.coderanch.com/t/245071/java-programmer-SCJP/certification/final-member-variables-interfaces

Why are all fields in an interface implicitly static and final?

An interface is intended to specify an interaction contract, not implementation details. A developer should be able to use an implementation just by looking at the interface, and not have to look inside the class which implements it.

An interface does not allow you to create an instance of it, because you cannot specify constructors. So it cannot have instance state, although interface fields can define constants, which are implicitly static and final.

You cannot specify method bodies or initializer blocks in an interface, although since Java 8 you can specify default methods with bodies. This feature is intended to allow new methods to be added to existing interfaces without having to update all the implementations. But you still cannot execute such a method, without first creating an instance implementing the interface.

Aside: Note that you can implement an interface with an anonymous inner class:

interface Foo {
String bar();
}

class FooBar {
Foo anonymous = new Foo() {
public String bar() {
return "The Laundromat Café";
};
}

You have to provide the full implementation of the interface for the anonymous inner class to compile.

new Foo() is initializing the anonymous inner class with its default constructor.

Constant Interface Anti-Pattern Clarification

I realised... the fact that the interface CAN be implemented by an individual if desired, leaves room for the issues pointed out above (i.e. namespace pollution, non-conventional use, exposure through public API ). So it's best to prevent the ability to implement the interface altogether. Hence, it's more appropriate to have a final class with a private constructor so that it can't be instantiated / extended.

public final class Constants
{
// to restrict instantiation
private Constants() {}

public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}

... and use that in combination with the import static.

import static Constants.PLANCK_CONSTANT;
import static Constants.PI;

public class Calculations
{
public double getReducedPlanckConstant()
{
return PLANCK_CONSTANT / ( 2 * PI );
}
}

Interface Constants vs Class Constants variables

First, never create a single class or interface for dumping all of your constants. I know it is tempting but after 1 or 2 years, that constant file will become very messy and unreadable. Instead, if a variable has a very close relationship with a class, it is better to put the constant variable in that class. Here is what Joshua Bloch advises :

If the constants are strongly tied to an existing class or interface, you should add them to the class or interface. For example, all of the boxed numerical primitive classes, such as Integer and Double, export MIN_VALUE and MAX_VALUE constants. If the constants are best viewed as members of an enumerated type, you should export them with an enum type. Otherwise, you should export the constants with a noninstantiable utility class.

Use Interface for declaring Constants or a Class

In terms of design both are bad. A class should have methods in your software in order to respect the definition of a class and the encapsulation principle. Interfaces are used to indicate similar behavior of classes and shouldn't be used to stock constants. However, a good solution would be to create a new class that is called Value. You can find more details here :

Should a collection of constants be placed in a class or interface?

Is public static final redundant for a constant in a Java interface?

Variables declared in Interface are implicitly public static final. This is what JLS 9.3 says :

Every field declaration in the body of an interface is implicitly public, static, and final. It is permitted to redundantly specify any or all of these modifiers for such fields.

Read through the JLS to get an idea why this was done.

Look at this SO answer:

Interface variables are static because Java interfaces cannot be instantiated in their own right; the value of the variable must be assigned in a static context in which no instance exists. The final modifier ensures the value assigned to the interface variable is a true constant that cannot be re-assigned by program code.



Related Topics



Leave a reply



Submit