What is the use of interface constants?
I am learning Java and just found that the Interface can have fields, which are public st开发者_如何学Catic 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?
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);
}
}
"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?
The fundamental issue
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.
Using Interface Constants is Good Practice.
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.
A silly reasoning - Interfaces were not intended by the founders of the Java language to be used that way?
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.
Use of Enum Constants is actually Horrible Practice.
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.
Constants are API Contract
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.
A strange presumption - What if the interface inadvertently gets implemented.
Yup. Anyone could inadvertently implement any interface inadvertently. Nothing will stand in the way of such inadvertent programmers.
Design and normalize your data-model against leakage
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.
Not using an IDE is bad practice
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.
A couple frameworks are designed to help programmers continue practicing bad habits efficiently.
OSGI is such a framework. And so is the decree against Interface Constants too.
Therefore the conclusive answer ...
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.
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.
Why use Interface Constant?
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.
Bad practice?
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)
It won't happen in the standard library
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.
Never-ending debate
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.
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.
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
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.
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.
- These common constants are intended to be known by the client to know more about these objects.
- So Constants Interface is indeed counter-intuitive for defining global constants, since interface is used to describe some objects, not all objects / no object (consider the meaning of global).
So I think if Constants Interface is not used for global constants, then it's acceptable:
- If these common constants have good names, they will recommend the implementor to use them (See my first point for the Example below)
- If a class want to sync up with those classes following the specification, just
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:
- From
Circle implements Drawable
, you immediately know thatCircle
is probably conformed to the constants defined inDrawable
, otherwise they have to choose a worse name since the good onesPI
andGOLDEN_RATIO
has already been taken! - Only these
Drawable
objects conform to the specificPI
andGOLDEN_RATIO
defined inDrawable
, there can be objects which are notDrawable
with different precision of pi and golden ratio.
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.
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);
orthis.add(SwingComponents.LINE_START, swingcomponent);
However this interface doesn't have methods...
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.
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.
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);
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
精彩评论