tags:

views:

5690

answers:

19

I've seen examples like this:

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

and supposed that I could have a Constants class to wrap constants in, declaring them static final. I know practically no Java at all and am wondering if this is the best way to create constants.

+23  A: 

That is perfectly acceptable, probably even the standard.

(public/private) static final TYPE NAME = VALUE;

where TYPE is the type, NAME is the name in all caps with underscores for spaces, and VALUE is the constant value;

As a side note: Variables that are declared final and are mutable can still be changed; however, the variable can never point at a different object.

For example:

public static final Point ORIGIN = new Point(0,0);

public static void main(String[] args){

    ORIGIN.x = 3;

}

That is legal and ORIGIN would then be a point at (3, 0).

jjnguy
You can even 'import static MaxSeconds.MAX_SECONDS;' so that you don't have to spell it MaxSeconds.MAX_SECONDS
Aaron Maenpaa
The previous comment about import static only applies to Java 5+. Some feel the shorthand isn't worth the possible confusion as to where the constant came from, when reading long code, MaxSeconds.MAX_SECONDS may be easier to follow then going up and looking at the imports.
MetroidFan2002
Because you can change the objetc like jjnguy have showed, is best if your constatns are immutable objects or just plain primitive/strings.
marcospereira
A: 

I wouldn't call the class the same (aside from casing) as the constant ... I would have at a minimum one class of "Settings", or "Values", or "Constants", where all the constants would live. If I have a large number of them, I'd group them up in logical constant classes (UserSettings, AppSettings, etc.)

Joel Martinez
Having a class called Constants was what I planned on doing, that was just a small example I found.
mk
+4  A: 

That's the right way to go.

Generally constants are not kept in separate "Constants" classes because they're not discoverable. If the constant is relevant to the current class, keeping them there helps the next developer.

Jason Cohen
+5  A: 

Just avoid using an interface:

public interface MyConstants {
    String CONSTANT_ONE = "foo";
}

public class NeddsConstant implements MyConstants {

}

It is tempting, but violates encapsulation and blurs the distinction of class definitions.

Indeed static imports are far preferable.
Aaron Maenpaa
A: 

To take it a step further, you can place globally used constants in an interface so they can be used system wide. E.g.

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

But don't then implement it. Just refer to them directly in code via the fully qualified classname.

Andrew Harmel-Law
The point about declaring them in an interface (and not implementing it) is that you can miss out the "public static final".
Tom Hawtin - tackline
Interfaces are for defining a behavioural contract, not a convenience mechanism for holding constants.
John Topley
+1  A: 

What about an enumeration?

Sébastien D.
+32  A: 

I would highly advise against having a single constants class. It may seem a good idea at the time, but when developers refuse to document constants and the class grows to encompass upwards of 500 constants which are all not related to each other at all (being related to entirely different aspects of the application), this generally turns into the constants file being completely unreadable. Instead:

  • If you have access to Java 5+, use enums to define your specific constants for an application area. All parts of the application area should refer to enums, not constant values, for these constants. You may declare an enum similar to how you declare a class. Enums are perhaps the most (and, arguably, only) useful feature of Java 5+.
  • If you have constants that are only valid to a particular class or one of its subclasses, declare them as either protected or public and place them on the top class in the hierarchy. This way, the subclasses can access these constant values (and if other classes access them via public, the constants aren't only valid to a particular class...which means that the external classes using this constant may be too tightly coupled to the class containing the constant)
  • If you have an interface with behavior defined, but returned values or argument values should be particular, it is perfectly acceptible to define constants on that interface so that other implementors will have access to them. However, avoid creating an interface just to hold constants: it can become just as bad as a class created just to hold constants.
MetroidFan2002
totally agree... this can be documented as a classical anti-pattern for large projects.
Das
+8  A: 

It is a BAD PRACTICE to use interfaces just to hold constants (named constant interface pattern by Josh Bloch). Here's Josh advices:

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.

Example:

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}

About the naming convetion:

By convention, such fields have names consisting of capital letters, with words separated by underscores. It is critical that these fields contain either primitive values or references to immutable objects.

Marcio Aguiar
+7  A: 

In Effective Java 2nd edition, it's recommended that you use enums instead of static ints for constants.

There's a good writeup on enums in Java here: http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

Note that at the end of that article the question posed is:

So when should you use enums?

With an answer of:

Any time you need a fixed set of constants

shelfoo
+2  A: 

I agree that using an interface is not the way to go. Avoiding this pattern even has its own item (#18) in Bloch's Effective Java.

An argument Bloch makes against the constant interface pattern is that use of constants is an implementation detail, but implementing an interface to use them exposes that implementation detail in your exported API.

The public|private static final TYPE NAME = VALUE; pattern is a good way of declaring a constant. Personally, I think it's better to avoid making a separate class to house all of your constants, but I've never seen a reason not to do this, other than personal preference and style.

If your constants can be well-modeled as an enumeration, consider the enum structure available in 1.5 or later.

If you're using a version earlier than 1.5, you can still pull off typesafe enumerations by using normal Java classes. (See this site for more on that).

Rob Dickerson
+4  A: 

The number one mistake you can make is creating a globally accessible class called with a generic name, like Constants. This simply gets littered with garbage and you lose all ability to figure out what portion of your system uses these constants.

Instead, constants should go into the class which "owns" them. Do you have a constant called TIMEOUT? It should probably go into your Communications() or Connection() class. MAX_BAD_LOGINS_PER_HOUR? Goes into User(). And so on and so forth.

The other possible use is Java .properties files when "constants" can be defined at run-time, but not easily user changeable. You can package these up in your .jars and reference them with the Class resourceLoader.

Yann Ramin
A: 

For Constants, Enum is a better choice IMHO. Here is an example

public class myClass {

public enum myEnum {
 Option1("String1", 2), 
 Option2("String2", 2) 
 ;
 String str;
            int i;

            myEnum(String str1, int i1) { this.str = str1 ; this.i1 = i }


}
A: 

A Constant, of any type, can be declared by creating an immutable property that within a class (that is a member variable with the final modifier). Typically the static and public modifiers are also provided.

public class OfficePrinter {
    public static final String STATE = "Ready";  
}

There are numerous applications where a constant's value indicates a selection from an n-tuple (e.g. enumeration) of choices. In our example, we can choose to define an Enumerated Type that will restrict the possible assigned values (i.e. improved type-safety):

public class OfficePrinter {
    public enum PrinterState { Ready, PCLoadLetter, OutOfToner, Offline };
    public static final PrinterState STATE = PrinterState.Ready;
}
Ryan Delucchi
A: 

One of the way I do it is by creating a 'Global' class with the constant values and do a static import in the classes that need access to the constant.

Javamann
+1  A: 

A single, generic constants class is a bad idea. Constants should be grouped together with the class they're most logically related to.

Rather than using variables of any kind (especially enums), I would suggest that you use methods. Create a method with the same name as the variable and have it return the value you assigned to the variable. Now delete the variable and replace all references to it with calls to the method you just created. If you feel that the constant is generic enough that you shouldn't have to create an instance of the class just to use it, then make the constant method a class method.

+3  A: 

A good object oriented design should not need many publicly available constants. Most constants should be encapsulated in the class that needs them to do its job.

Bradley Harris
Or injected into that class via the constructor.
WW
+2  A: 

I prefer to use getters rather than constants. Those getters might return constant values, e.g. public int getMaxConnections() {return 10;}, but anything that needs the constant will go through a getter.

One benefit is that if your program outgrows the constant--you find that it needs to be configurable--you can just change how the getter returns the constant.

The other benefit is that in order to modify the constant you don't have to recompile everything that uses it. When you reference a static final field, the value of that constant is compiled into any bytecode that references it.

big_peanut_horse
+1  A: 

FWIW, a timeout in seconds value should probably be a configuration setting (read in from a properties file or through injection as in Spring) and not a constant.

Tim Howland
+1  A: 

Creating static final constants in a separate class can get you into trouble. The Java compiler will actually optimize this and place the actual value of the constant into any class that references it.

If you later change the 'Constants' class and you don't do a hard re-compile on other classes that reference that class, you will wind up with a combination of old and new values being used.

Instead of thinking of these as constants, think of them as configuration parameters and create a class to manage them. Have the values be non-final, and even consider using getters. In the future, as you determine that some of these parameters actually should be configurable by the user or administrator, it will be much easier to do.

Kevin Day