2

I want some String values to be available/accessible to me throughput the application in Java. Different classes will need them. I want to know the best possible way to keep and access those values throughout the application.

  1. One way I know is to use Enum pattern in Java. Where I can associate a String value with each enum and then access it. Like given here. Best way to create enum of strings?

  2. Second is to maintain a class of constants with String values.

What is the possible best way so that good design will be followed and everything will be accessed cleanly.

I would like to know.

public class StringValues
{
   public static final String ONE = "one";
   public static final String TWO = "two";
}

I am adding a little more detail.

I am going to create DB queries with these short name Strings. So while instantiating database I will use all the Strings in one place and will create queries.

But after query creation I will need a fragment/part of that String pool for a specific class so that I can register listener for the selected class not for all the Strings in the pool. Every class should know that It needs only 1-2 Strings names to register runtime listener not all the String names.

I need all Strings at one time(during start of application) then I will just need 2 or 3 or more of them but not all.

Here is the code to make you understand my exact design problem.

/**
*This class will be used to create Views in Database.
*/
class Views
{
    public static final String BY_NAME = "byName";
    public static final String BY_DATE = "byDate";
    public static final String BY_GENDER = "byGender";

    //For every String I am going to create Views in Couchbase.
}

/**
*This class knows to which Views it needs to listen to. If any change in its views occurs then
* it will take action. In case of byDate change it is intended to take an action.
*/
public class NewestMember
{
    String[] viewsToQueryFor = {"byDate"};

    //This class will call only these views and will register for them.
}


public class Male
{
    String[] viewsToQueryFor = {"byName", "byGender"};

    //This class will call only these views and will register for them.
}


public class Female
{
    String[] viewsToQueryFor = {"byName", "byGender"};

    //This class will call only these views and will register for them.
}

I do not want to do this. For this I have extra overhead of keeping String values in other classes.

Community
  • 1
  • 1
Master
  • 2,945
  • 5
  • 34
  • 65
  • 1
    Id depends are these values really constant or maybe configurable. If the second, it's better to save them in *.properties files. – Ashot Karakhanyan Feb 08 '14 at 16:32
  • I would go for an interface instead of a class (you don't have to explicitly write `public static final` for each constant, because that's explicit in interfaces). This does not mean, that you should actually *implement* the interface, but just refer to it in a static manner. Personally I would not like the `enum` variant, because it leads to verbosity (e.g. `StringEnum.VALUE_1.getString()` instead of `StringConstants.VALUE_1`). – qqilihq Feb 08 '14 at 16:33
  • 3
    Usually one would put the constants in the class that actually requires them. Avoid the [Constant interface antipattern](http://en.wikipedia.org/wiki/Constant_interface). – Boris the Spider Feb 08 '14 at 16:34
  • @BoristheSpider in this case, I will have to write a single string at more than one place if needed by many classes. – Master Feb 08 '14 at 16:36
  • @Hoosier: not if the constant is public. See my answer, which shows Boris's thought with example code. – JB Nizet Feb 08 '14 at 16:37
  • 1
    @Hoosier if there are that many constants then you probably have some design problem - consider grouping constants into `enum` instances that describe their purpose, e.g. `public enum CompassPoint`, `public enum Gender` etc. An advantage of using `enum` is that `Gender.MALE` cannot be passed into a method that requires a `CompassPoint` so the method does not need to check for invalid input. You can also hang more data off of an `enum`. – Boris the Spider Feb 08 '14 at 16:39
  • 1
    From the update to the question this seems to be a classic XY problem. There should be no constants at all. Queries should be defined in a DAO layer and used there. They should **not** be built through string concatenation but through prepared statements. – Boris the Spider Feb 08 '14 at 16:53
  • 1
    Now that you provided code, and if I understand it correctly, I would say that I stick to my initial answer. The view names apply to a specific type of data. So these constants should probably be in PersonView, and PersonView should probably be an enum. It makes no sense to apply a `byGender` view on a collection containing cars or appointments or whatever. For cars, you would have a CarView class or enum containing BY_COLOR and BY_MODEL. – JB Nizet Feb 08 '14 at 17:37
  • So you will encourage me to use Enum pattern? – Master Feb 08 '14 at 17:43
  • I still have a very partial understanding of your problem, but given what I understood, then yes, you should probably have a PersonView enum containing all the views that can be applied on a collection of Persons. – JB Nizet Feb 08 '14 at 17:46
  • Okay. But you have not specified enum in your answer. Update that before I accept it. – Master Feb 08 '14 at 17:49

3 Answers3

4

The second one is fine. But I wouldn't create a single class to contain all the unrelated constants. That doesn't scale, and isn't natural. Instead, define the constants in the class where they belong. For example:

public class Victim {
    public static class DEFAULT_MALE_NAME = "John Doe";
    public static class DEFAULT_FEMALE_NAME = "Jane Doe";
    ...
}

public class CreditCard {
    public static final String DEFAULT_TYPE = "Visa";
    ...
}

EDIT:

Now that you provided some code, it seems that you should in fact define one or several enums, that would each encapsulate the concept of a View applied to a given collection.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • But according to my requirement I need to keep a pool of all my constants. From that pool I will create queries and then for any requirement a class will have a small part of those pool strings to call them for its own purpose. – Master Feb 08 '14 at 16:39
  • We won't understand what you mean if you don't tell us what these constants are, and what you want them for. Just imagine if all the constants of the JDK were defined in a single class: it would have thousands of unrelated constants, with huge names to make them unique, and it would be a mess. There's no reason to put unrelated constants in a single class. Maybe your constants are closely related, then putting them in a single class is OK. – JB Nizet Feb 08 '14 at 16:42
  • I am going to update question's info. Please wait a little. I need your help. – Master Feb 08 '14 at 16:44
  • I have updated my question. It will help you to know what problem I am actually facing. – Master Feb 08 '14 at 16:49
  • I still don't understand much. Maybe a code example would help. But I agree with Boris's comment: it seems to be an XY problem, and you should probably not have constants at all. – JB Nizet Feb 08 '14 at 17:04
  • So what could be the best way. You somewhere got my problem; I need all Strings at one time(during start of application) then I will just need 2 or 3 or more of them but not all. – Master Feb 08 '14 at 17:06
  • Read http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem, and understand that, until we understand what you want to achieve, there's no point in trying to answer your question. – JB Nizet Feb 08 '14 at 17:09
  • I have read that but the added description is what I want answer for. I simply do not want to write Strings everywhere. But I also need them all at once. – Master Feb 08 '14 at 17:16
  • The added description doesn't help me, and doesn't seem to help others understanding what you want to achieve. You've been asked several times already to provide example code. Why don't you do that? – JB Nizet Feb 08 '14 at 17:17
  • I am going to update question with code snippet of my problem – Master Feb 08 '14 at 17:22
2

Since you cannot extend an enum later, the best way is to use constants, i.e. public static final.

Hannes
  • 2,018
  • 25
  • 32
1

I would group the constants and use the second suggestion where the name of the class should be something domain specific instead of only "constants something". Consider a pool of data base field names where each class could represent a table. I would only use this pattern if

  1. I require a lot of such values such that I would prefer some grouping.
  2. These values are used throughout several parts of my application and I do not want to repeat them in order to avoid for exaple typos.

Otherwise these values should be defined as private constant fields within the using class.

In addition, I would make such classes final and add private constructors that throw an AssertionError (otherwise such constant holer classes could still be created refectively). This makes it clear to every user that these classes should never be used for something else then their constants. I would further avoid interfaces, because they tend to get implemented in order to allow for some sort of static import even though these constant classes do not really represent an actual domain type. This adds some unneccesary verbosity to your application.

Note that Strings (and primitives) are compile time constants and will be inlined by the compiler. This means that these constant holder classes do never get loaded at runtime and there is absolutely no performance or memory penaltiy when using them. It will be just as if you copy-pasted the String to each location it is used. Good grouping is therefore the highest priority. This inlineing does not apply for "string enums" which is why I would discourage their use. If your constant types get more complex than just Strings, I would again consider enums since they can represent interface types and offer a concise way of defining such constants.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192