Reputation: 53491
I am learning Java and just found that the Interface can have fields, which are public static and final. I haven't seen any examples of these so far. What are some of the use cases of these Interface Constants and can I see some in the Java Standard Library?
Upvotes: 167
Views: 153489
Reputation: 15703
If it's less than 64 constants I would favor Enums instead. If it's a smaller number, under a dozen or so I've used Interfaces at times, even though yes I've read it's an anti-pattern.
I had an app I worked on once that had hundreds of Interface constants and to me that was a code smell. I think a static import would have been better for that use case, but I'm guessing because I assume performance might be better.
Also, there is a post called: The Java Constants Interface that explains the issue of "field shadowing" and shows code as to how a value inside a class implementing an interface, COULD be overridden, which I thought was interesting. He makes a valid case with tests rather than opinions, which is all I had found in the past.
Field or variable shadowing definition (from What is field shadowing?):
Variable shadowing happens when we define a variable in a closure scope with a variable name that is the same as one for a variable we've already defined in an outer scope.
So to summarize, use Enums or static imports for this over interfaces as a general rule.
Upvotes: 0
Reputation: 21654
"The constant interface pattern is a poor use of interfaces"
Whoever concocted this hypothesis, however a guru he/she may be, concocted it on the basis of the need to continue implementing bad habits and practices efficiently. The hypothesis is based on the promotion of the validity of bad software design habits.
I wrote a response rebuttal against that hypothesis here: What is the best way to implement constants in Java? explaining the baseless-ness of this hypothesis.
For 10 years that question had stayed open, until it was closed within 2 hours after I posted my reasons dejustifying this hypothesis, thus exposing UNWILLINGness for debate by those who hold on to this misguided hypothesis dearly.
These are the points I expressed against the hypothesis
The basis for holding this hypothesis is the need for methods and RESTRICTIVE rules to cope with the effects of bad software habits and methodologies.
The proponents of the sentiment "The constant interface pattern is a poor use of interfaces" are unable to provide any reasons other than those caused by the need to cope with the effects of those bad habits and practices.
Solve the fundamental issue.
And then why not make full use and exploit every language feature of the Java language structure to your own convenience. No Jackets Required. Why invent rules to barricade your ineffective lifestyle to discriminate and incriminate more effective lifestyles?
is information organisation. Information mediating the process, nd the behaviour of that information should first be understood, along with the so-called business rules - before engineering or supplementing solutions to the process. Such method of information organization was called data normalization a few decades ago.
Then only the engineering of a solution be possible because aligning the granularity and modularity of the components of a solution with the granularity and modularity of the components of the information is the optimal strategy.
There are two or three significant obstacles toward organizing information.
The lack of perception for the need of data-model "normalization".
EF Codd's statements on data normalization are flawed, defective and ambiguous.
The latest fad masquerading as agile engineering is the misguided notion that one should not plan and condition the organization of modules ahead because you can refactor as you go. Refactoring and continuous change without being impeded by future discoveries is used as the excuse. Essential discoveries of behaviour of process information is then, by using accounting tricks to delay profits and assetization, wherefore essential knowledge and their treatment is deemed not needed now.
Don't make up rules or issue any fatwa against it just because you love your ad-hoc hit-and-run programming habits.
Do not ban gun ownership with the reason that there are people who either do not know how to handle guns or are prone to abuse guns.
If the rules you concoct are meant for programming novices unable to code professionally and that you count yourself amongst them then say so - do not declare your fatwa as applicable to properly normalized data-models.
I don't care what the original intentions of the founding fathers had for the US Constitution. I don't care about the unwritten uncodified intentions. I only care about what is literarily codified in the written Constitution and how I can exploit them for the effective functioning of society.
I only care about what the Java language/platform specs allow me and I intend to exploit them to the full to afford me a medium to express my software solutions efficiently and effectively. No jackets required.
It requires writing extra code to map parameter to value. The fact that the founders of Java did not provide for parameter-value mapping without your writing that mapping code demonstrates Enum Constants are just as unintended use of Java language.
Especially since you are not encouraged to normalize and componentize your parameters, there would be a false impression that parameters mixed into an Enum bag belong to the same dimension.
Don't forget that. If you designed and normalized your data-model, and they include constants,then those constants are contracts. If you did not normalize your data-model, then you should conform to fatwas given on how to practice restrictive coding to cope with that bad habit.
Therefore, Interfaces are a perfect way of implementing Constants' contract.
Yup. Anyone could inadvertently implement any interface inadvertently. Nothing will stand in the way of such inadvertent programmers.
Do not place restrictive decrees to protect presumed bad practices that cause leaking of uncontracted/stray parameters into API. Solve the fundamental issue, rather than place the blame on Interface Constants.
A normal functioning and EFFECTIVE programmer is not there to prove how long she can stay underwater, how far she could walk in blistering heat or wet thunderstorms. She is to use an efficient tool like a car or bus or at least a bike to take her 10 miles to work everyday.
Do not place restrictions on fellow programmers just because you have an esoteric asceticism obsession with IDE-less programming.
OSGI is such a framework. And so is the decree against Interface Constants too.
Interface constants are an effective and efficient way to place into Contract well-designed and normalized components of a data-model.
Interface constants in an appropriately named private interface nested in a class file are also good practice to group all your private constants rather than scatter them all over the file.
Upvotes: 34
Reputation: 597
There's one context in which interface constants are superior to static final fields: enumerations. Interface constants can be used in enumerated constant declarations in a fashion that makes them also available as discrete values attached to the enumeration without the need for any additional specification. For example, this interface:
public interface Name {
String MANNY = "Manny";
String MOE = "Moe";
String JACK = "Jack";
String getName();
}
... can supply string constants that can be used in enumerated constants like this:
public enum PepBoys implements Name {
BOY1(MANNY),
BOY2(MOE),
BOY3(JACK);
private String name;
PepBoys(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
Values for annotation attributes must be constant values, and (ironically) enumerated constants don't qualify as 'constant' in this context. However, string constants defined in an interface do so qualify:
@MyAnnotation(PepBoys.MANNY)
public void annotatedMethod() {
...
}
Such string constants can easily be mapped back to the enumerated constants they're associated with, and each constant is declared only once. There are other ways to accomplish similar results, but none are this concise and all require at least two parallel declarations.
Upvotes: 2
Reputation: 1021
I came across this old question several times now and the accepted answer still confuse me. After a lot of thinking, I think this question can be further clarified.
Just compare them:
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
vs
public interface Constants {
double PI = 3.14159;
double PLANCK_CONSTANT = 6.62606896e-34;
}
Same usage. Much less code.
I think @Pascal Thivent 's answer has the wrong emphasis, here is my version of it:
Putting static members into an interface (and implementing that interface) is a bad practice.
The quote from Effective Java has the assumption of the constant interface being implemented by others, which I think should not (and will not) happen.
When you create an constant interface named something like Constants
, it should not be implemented by anyone. (though technically possible, which is the only issue here)
The standard library cannot afford any possible misuse of the design, so you just won't see any there.
However, for daily projects of normal developers, using constants interface is a lot easier because you do not need to worry about static
, final
, empty constructor
, etc, and it will NOT cause any bad design issue. The only downside I can think of is that it still has the name of "interface", but nothing more than that.
At the end, I think everyone is just quoting from books, and giving opinions and justifications to their stands. No exception for me. Maybe the decision is still up to the developers of each project. Just go ahead to use it if you feel comfortable. The best we can do is to make it consistent throughout the project.
Upvotes: 30
Reputation: 2901
Two points about interface:
An interface describes a subset of what an object which implements it can do. (This is the intuition)
An interface describes common constants followed by objects which implement it.
So I think if Constants Interface is not used for global constants, then it's acceptable:
implements
it (and, of course, use these common constants in implementation).Example:
interface Drawable {
double GOLDEN_RATIO = 1.618033988;
double PI = 3.141592653;
...
// methods
...
}
public class Circle implements Drawable {
...
public double getCircumference() {
return 2 * PI * r;
}
}
void usage() {
Circle circle = new Circle(radius: 3.0);
double maxRadius = 5.0;
if ( circle.getCircumference() < 2 * Circle.PI * maxRadius ) {
...
}
}
In this example:
Circle implements Drawable
, you immediately know that Circle
is probably conformed to the constants defined in Drawable
, otherwise they have to choose a worse name since the good ones PI
and GOLDEN_RATIO
has already been taken!Drawable
objects conform to the specific PI
and GOLDEN_RATIO
defined in Drawable
, there can be objects which are not Drawable
with different precision of pi and golden ratio.Upvotes: 2
Reputation: 161
There are answers that are very resonable.
But I have some thoughts about this question. (may be wrong)
In my opinion, the fields in a interface, should not be constants to the whole project, they are only means for the interface and the interfaces extend it and the classes which are implement these interfaces or have a close relation with them. They should be used within a certain range not global.
Upvotes: 4
Reputation: 68962
Joshua Bloch, "Effective Java - Programming Language Guide":
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.
Upvotes: 4
Reputation: 1859
I came across this question and thought I'd add something that was not mentioned. In general, I agree with Pascal's answer here. However, I don't think constants on an interface are "always" an antipattern.
For example, if the constants that you are defining are part of a contract for that interface, I think the interface is a great place for the constants. In some cases, its just not appropriate to privately validate your parameters without exposing the contract to the users of your implementation. Without a public facing contract, users can only guess what your validating with, short of decompiling the class and reading your code.
So if you implement an interface and the interface has the constants you use in ensuring your contracts (like integer ranges for example), then a user of your class can be sure they are using the interface instance correctly by checking against the constants in the interface themselves. This would be impossible if the constants were private to your implementation or your implementation was package private or something.
Upvotes: 2
Reputation: 570335
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);
}
}
Upvotes: 242
Reputation: 2406
fields should be declared in an interface so that they are easier to share and can be referenced without introducing extra coupling.
Source: Java Developer Tools Coding Style
Upvotes: -3
Reputation: 347
I use interface constants when dealing with shared constants between classes.
public interface TestConstants
{
String RootLevelConstant1 = "RootLevelConstant1";
interface SubGroup1
{
String SubGroupConstant1 = "SubGroup1Constant1";
String SubGroupConstant2 = "SubGroup1Constant2";
}
interface SubGroup2
{
String SubGroupConstant1 = "SubGroup2Constant1";
String SubGroupConstant2 = "SubGroup2Constant2";
}
}
The grouping is a huge asset, especially with a large set of constants.
To use, you simply chain them together:
System.out.println(TestConstants.SubGroup1.SubGroupConstant1);
System.out.println(TestConstants.SubGroup2.SubGroupConstant1);
System.out.println(TestConstants.RootLevelConstant1);
Upvotes: -1
Reputation: 19546
The javax.swing.SwingConstants
interface is an example which got static fields which are used among the swing classes. This allows you to easily use something like
this.add(LINE_START, swingcomponent);
this.add(this.LINE_START, swingcomponent);
or this.add(SwingComponents.LINE_START, swingcomponent);
However this interface doesn't have methods...
Upvotes: 0
Reputation: 55444
They are useful if you have common constants that will be used in classes that implement the interface.
Here's an example: http://www.javapractices.com/topic/TopicAction.do?Id=32
But note that the recommended practice is to use static imports instead of constants in interfaces. Here's a reference: http://www.javapractices.com/topic/TopicAction.do?Id=195
Upvotes: 4