Define Constants In Interfaces

This needs some generalizing.

Perhaps this belongs in InterfacesForDefiningConstants?

I am working on some code to deal with multiple mouse buttons. In order to distinguish the mouse buttons, I have to write code like:

class MouseMouser? implements MouseListener? {
public void mousePressed(MouseEvent? e) {
int buttons = e.getModifiers() & (InputEvent?.BUTTON1_MASK | InputEvent?.BUTTON2_MASK | InputEvent?.BUTTON3_MASK);
switch (buttons) {
case InputEvent?.BUTTON1_MASK:
                                // ...
                        case InputEvent?.BUTTON2_MASK:
                                // ...
                        case InputEvent?.BUTTON3_MASK:
// ...
}
}
// ...
}

Having to specify InputEvent? every time I talk about a mouse button is a real pain. Including the relevant constants into MouseMouser? is annoying and loses when new constants are added to InputEvent?.

Therefore:

The input event constants should appear in the interface InputEventConstants?. The above code then becomes:

class MouseMouser? implements MouseListener?, InputEventConstants? {
public void mousePressed(MouseEvent? e) {
int buttons = e.getModifiers() & (BUTTON1_MASK | BUTTON2_MASK | BUTTON3_MASK);
switch (buttons) {
case BUTTON1_MASK:
                                // ...
                        case BUTTON2_MASK:
                                // ...
                        case BUTTON3_MASK:
// ...
}
}
// ...
}

The above code is still somewhat unwieldly, but it is an improvement over the original.

-- BillTrost


This idiom is explored in some detail at http://www.javaworld.com/javaworld/javatips/jw-javatip50.html

The author suggests defining constants in a nested interface -- so that the import of a "constants" interface identifies the class for which they are required -- and also combines the idiom with EnumeratedTypesInJava.

--NatPryce

But they also say that this is not possible as of JDK 1.3??

--semplice


It's widely considered an AntiPattern, because interfaces should define types, not be a dumping ground for global variables. Item 17 in JoshuaBloch's book EffectiveJava is "Use interfaces only to define types".

One of the rumored changes in Java 1.5 allows a class to import constants from a class. That is, import InputEvent?.* would allow code to reference BUTTON1_MASK without the qualifier.

I've been taught (and passed on) this wisdom, but today I can find no reason to accept it. Can you give a reason not to use Java's interfaces as dumping grounds for constants (not global variables)?

I think grouping constants in a java interface is a good design. However I had a hard time convincing a C# programmer about this though. But enums would be the only reason when you do not want to use java interfaces. However I do want enums that can handle strings, C#'s enums cannot handle strings. -semplice

grouping constants in a java interface is a good design. How so? Is the collection of constants in a namespace somehow defining behavior that a service provider might implement, or that a client might use? What understanding can someone perusing the code get when seeing a class that implements this interface that has defines behaviors? It's bad design. It says, "I have globals and I don't know who is responsible for them or how they relate to the system, to I'll just put them out there."

No it doesn't. They are constants. They are not global. Putting them in an interface associates them with a package (namespace) (just like putting them in a class does).

So how would one define constants in java? Where would the constants go if other classes which want to use them?

How about on the class that defines the behaviors and operations that care about those constants? For example, E and PI are defined on java.lang.Math. MAX_VALUE is defined on Integer and on Long, (and the other numeric types) because they are different for each type. That makes sense, because those are the classes that most care about those values, and any other class that cares about those values is probably going to be a user of the defining class.

But, as the creator of this page argues, it leads to more verbose code. You can't add "implements java.lang.Math" to the declaration of a class that makes extensive use of constants defined in the Math class.

Sure E and PI are defined in java.lang.Math but what about constants that are not associated with a class. What if I do not have "a" class that care about these values. What if I have a group of classes that need these constants?

f cd vrbsty is imprt dnt cd n jv. (Translation: If code verbosity is important don't code in Java). Code is only typed one time, if that, but is read many many times. Clarity of meaning is paramount. That said, Java 1.5 will allow importing at a finer grain, including "import java.lang.Math.PI". The question of what the code should look like if it deals with both Integer.MAX_VALUE and Long.MAX_VALUE is left as an exercise for the reader.


EditText of this page (last edited January 10, 2005) or FindPage with title or text search