64

I'd like to have Java constant strings at one place and use them across whole project (many classes).

What is the recommended way of achieveing this?

Danijel
  • 8,198
  • 18
  • 69
  • 133
  • what about a static class with static methods that return constant strings? – Nadir Sampaoli Jun 05 '12 at 11:03
  • 5
    This is not a recommended design method for java. Put your constants in the classes where they are relevant. – beerbajay Jun 05 '12 at 11:04
  • @beerbajay But I need those strings in a few classes, what is recommended way of doing it? – Danijel Jun 05 '12 at 11:08
  • 1
    @Danijel you'll still be able to use them across different classes if you do this the way beerbajay advises. Just make the fields static, public and final. – toniedzwiedz Jun 05 '12 at 11:10
  • 1
    It depends on your specific use-case. Usually there is one logical "master" location for such information, so you put the constants there, then reference that class and constant (e.g. `MyClass.MY_CONSTANT`) from the other places you need the information. If you find yourself needing a "constants class", it's usually an indication of not fully thought through design. – beerbajay Jun 05 '12 at 11:10
  • what its performance impact will it be better?or worse? – shareef Jul 10 '17 at 18:17

10 Answers10

57
public static final String CONSTANT_STRING="CONSTANT_STRING";

constants should be:

  1. public - so that it can be accessed from anywhere
  2. static - no need to create an instance
  3. final - since its constants shouldnt be allowed to change
  4. As per Java naming convention should be capitalized so that easy to read and stands out in Java documentation.

There are instances where interfaces are used just to keep constants, but this is considered a bad practice because interfaces are supposed to define the behavior of a type.

A better approach is to keep it in the class where it makes more sense.

for e.g.

JFrame has EXIT_ON_CLOSE contant, any class which subclasses JFrame will have access to it and it also makes sense to keep in JFrame and not in JComponent as not all components will have an option to be closed.

Kartik Chugh
  • 1,104
  • 14
  • 28
mprabhat
  • 20,107
  • 7
  • 46
  • 63
  • 12
    +1 for a good answer. Altho using an interface for this purpose is considered bad practice which should be mentioned – John Snow Jun 05 '12 at 11:10
  • 2
    @Jimmy: why using interfaces is a bad practice?? – Surender Thakran Jun 05 '12 at 11:19
  • 4
    interfaces are contract using them just to hold constants doesnt make sense – mprabhat Jun 05 '12 at 11:20
  • 1
    @WickeD using interface is not bad practice, but using interface to hold constants are :) please read this link for a more detailed explanation: http://stackoverflow.com/questions/320588/interfaces-with-static-fields-in-java-for-sharing-constants/320642#320642 – John Snow Jun 05 '12 at 11:38
  • 1
    Is it still bad practice to make an interface or class containing constants if they apply to all classes in a package but not to any one specifically? For example, a log message prefix string. – jacobq Jul 30 '13 at 15:48
  • Just EXIT_ON_CLOSE is an example of a constant in an interface: it isn't in JFrame, but in the interface WindowConstants. Why? To be used in JInternalFrame and JDialog too. – Nic Stray Jul 17 '21 at 19:56
27

As @mprabhat answered before, constants should be public, static, final, and typed in capital letters.

Grouping them in a class helps you:

  1. Don't need to know all the constants you have. Many IDEs (like Eclipse) show you the list of all the fields a class has. So you only press CTRL+SPACE and get a clue of which constants you can use.

  2. Making them typesafe at compile time. If you used Strings, you might misspell "DATABASE_EXCEPTION" with "DATABSE_EXSCEPTION", and only notice during execution (if you are lucky and notice it at all). You can also take profit of autocompletion.

  3. Helping you save memory during execution. You'll only need memory for 1 instance of the constant. I.E: (a real example) If you have the String "DATABASE_EXCEPTION" 1000 times in different classes in you code, each one of them will be a different instace in memory.

Some other considerations you might have:

  1. Add javadoc comments, so programmers who use the constants can have more semantic information on the constant. It is showed as a tooltip when you press CTRL+SPACE. I.E:

    /** Indicates an exception during data retrieving, not during connection. */
    public static final String DATABASE_EXCEPTION = "DATABASE_EXCEPTION";
    /** Indicates an exception during the connection to a database. */
    public static final String DATABASE_CONNECTION_EXCEPTION =" DATABASE_CONNECTION_EXCEPTION";
    
  2. Add semantic to the identifier of the constant. If you have the constant "Y", and sometimes means yes and other times year, consider using 2 different constants.

    public static final String Y = "Y"; // Bad
    public static final String YEAR = "Y";
    public static final String YES = "Y"; 
    

    It will help you if, in the future, decide to change the values of the constants.

    /** Year symbol, used for date formatters. */
    public static final String YEAR = "A"; // Year is Año, in Spanish.
    public static final String YES = "S"; // Yes is Sí, in Spanish.
    
  3. You might not know the value of your constants until runtime. IE: You can read them from configuration files.

    public class Constants
    {
      /** Message to be shown to the user if there's any SQL query problem. */
      public static final String DATABASE_EXCEPTION_MESSAGE; // Made with the 2 following ones.
      public static final String DATABASE_EXCEPTION = "DATABASE_EXCEPTION";
      public static final String MESSAGE = "MESSAGE";
    
      static {
        DATABASE_EXCEPTION_MESSAGE = DATABASE_EXCEPTION + MESSAGE; // It will be executed only once, during the class's [first] instantiation.
      }
    

    }

  4. If your constants class is too large, or you presume it'll grow too much in the future, you can divide it in different classes for different meanings (again, semantic): ConstantDB, ConstantNetwork, etc.

Drawbacks:

  1. All the members of your team have to use the same class(es), and the same nomenclature for the constants. In a large project it wouldn't be strange to find 2 definitions:

    public static final String DATABASE_EXCEPTION = "DATABASE_EXCEPTION";
    public static final String EXCEPTION_DATABASE = "DATABASE_EXCEPTION"; 
    

    separated several hundreds of lines or in different constant classes. Or even worse:

    /** Indicates an exception during data retrieving, not during connection. */
    public static final String DATABASE_EXCEPTION = "DATABASE_EXCEPTION";
    /** Indicates an exception during data retrieving, not during connection. */
    public static final String EXCEPTION_DATABASE = "EXCEPTION_DATABASE"; 
    

    different identifiers, for different values, having the same meaning (and used for the same purposes).

  2. It might make readability worse. Having to write more for doing the same:

    if ("Y".equals(getOptionSelected()) {
    

    vs

    if (ConstantsWebForm.YES.equals(getOptionSeleted()) {
    
  3. How should constants be ordered in the class? Alphabetically? All related constants together? In order as they are created/needed? Who sould be responsible of the order being correct? Any (big enough) reordering of constants would be seen as a mess in a versioning system.

Well, it's taken longer than what I expected. Any help/critics is/are welcome.

J.A.I.L.
  • 10,644
  • 4
  • 37
  • 50
21

You should create a class of the constants that stores all the constants.

like ProjectNameConstants.java

which contains all the constant string static as you can access it through the classname.

e.g.

classname :  MyAppConstants.java

public static final String MY_CONST="my const string val";

you can access it as

MyAppConstants.MY_CONST
Hemant Metalia
  • 29,730
  • 18
  • 72
  • 91
  • 2
    either that or you define it as a "public static final String" in the object that is responsible for this string – Udi Cohen Jun 05 '12 at 11:04
  • 1
    why would you do this? My gut feeling tells me this is a terrible idea but I'm happy to be proved the contrary. – B B Sep 20 '16 at 13:19
  • 1
    @Bruno Its better idea to keep all related constants in same file. like all the sql query constants related to one module should be in one java constant like that. – Hemant Metalia Sep 21 '16 at 06:55
  • Put constants with their classes. Don't create a separate class just for the constants. The sql query constants should be with the DAO class, etc. Exceptions to this might be e.g. an enum class for a bunch of strings that are all the same "thing" (planet names is the typical example). – Zac Thompson Oct 08 '16 at 21:50
9

Best practice is to use Java Enum (After Java 5)

Problems with the class approach:

  1. Not typesafe
  2. No namespace
  3. Brittleness

Please check java docs.

public enum Constants {

    CONSTANT_STRING1("CONSTANT_VALUE1"), 
    CONSTANT_STRING2("CONSTANT_VALUE2"), 
    CONSTANT_STRING3("CONSTANT_VALUE3");

    private String constants;

    private Constants(String cons) {
        this.constants = cons;
    }
}

Enums can be used as constants.

Edit: You can call this Constants.CONSTANT_STRING1

shim
  • 9,289
  • 12
  • 69
  • 108
amicngh
  • 7,831
  • 3
  • 35
  • 54
  • Those problems (typesafe, namespace and brittleness) happened with the old **Enum** approach (as a pattern, prior to Java 5). See [`enums` at the JavaDoc](http://docs.oracle.com/javase/1.5.0/docs/guide/language/enums.html) – J.A.I.L. Sep 06 '12 at 10:53
  • 4
    The way to call it isn't `Constants.CONSTANT_STRING1`, as it returns something of type `Constants`. You'd have to call it `Constants.CONSTANT_STRING1.toString()` or `Constants.CONSTANT_STRING1.name()`. – J.A.I.L. Sep 06 '12 at 10:57
  • As J.A.I.L. commented, your current code example does *not* work. Your call returns an object of type `Constants` rather than a `String` as desired in the Question. – Basil Bourque Jun 02 '17 at 23:45
4

Create a class called Constants at the base of your main package (i.e. com.yourcompany) with all your constants there. Also make the the constructor private so no object will be created from this class:

public class Constants {

    private Constants() {
        // No need to create Constants objects
    }

    public static final String CONSTANT_ONE = "VALUE_CONSTANT_ONE";
    public static final String CONSTANT_TWO = "VALUE_CONSTANT_TWO";
}
Eduardo Sanchez-Ros
  • 1,777
  • 2
  • 18
  • 30
3
public class SomeClass {
    public static final String MY_CONST = "Some Value";
}

If it is supposed to be a pure constants class then make the constructor private as well.

public class Constants {
    public static final String CONST_1 = "Value 1";
    public static final int CONST_2 = 754;

    private Constants() {
    }
}

Then it won't be possible to instantiate this class.

maba
  • 47,113
  • 10
  • 108
  • 118
  • 2
    It's better to just make it `static`, you shouldn't use this "private constructor" approach when there are better options built into Java. – Petrus K. Mar 18 '15 at 01:01
  • @Ryuji You are totally wrong and you are mixing that up with C#. Take a look here for example: http://stackoverflow.com/a/7486111/1350762 – maba Mar 18 '15 at 06:07
2

You should break up your constants into groups they belong, like where they'll be used most, and define them as public static final in those classes. As you go along, it may seem appropriate to have interfaces that define your constants, but resist the urge to create one monolithic interface that holds all constants. It's just not good design.

Thom
  • 14,013
  • 25
  • 105
  • 185
1

I guess the correct answer you're looking for is

import static com.package.YourConstantsClass.*;
Dinesh
  • 1,711
  • 2
  • 20
  • 41
0

Create a public class and for each constant string create a field like this

public static final String variableName = "string value";

0
public enum Constants {

CONSTANT_STRING1("CONSTANT_VALUE1"), 
CONSTANT_STRING2("CONSTANT_VALUE2"), 
CONSTANT_STRING3("CONSTANT_VALUE3");

private String constants;

private Constants(String cons) {
    this.constants = cons;
}
    @JsonValue
@Override
public String toString() {
    return constants;
}

}

Use it Constants.CONSTANT_STRING1.toString()

Nikhil Dinesh
  • 3,359
  • 2
  • 38
  • 41