What is the overall advantage (in terms of memory management, etc.) of creating a separate constants file, like below class "Constants", over directly writing in Java file like stringVar.equals("name")?
public final class Constants {
// Hide the constructor
private Constants(){}
public static String NAME="name";
}
I know that even if we write use "name" 2 times (as below), only one literal will be created in String pool?
stringVar1.equals("name") and stringVar2.equals("name")
One reason would be to reuse it (and as a consequence prevent bugs from typos).
If you are using an IDE, it also becomes easier to perform a usage-lookup in a bit more non-ambiguous manner than plain string search.
The other as already noted in the comment, would be memory but as I see it, the above two reasons are far more significant - in general usage. My bad. Looks like memory has not much to do with it - atleast in case of static-final fields .
It's not about efficiency; it's about maintainability.
The constant both defines the value "name" in a single place, and associates a constant name (you chose NAME) with it.
In your example, the constant name doesn't tell us anything. But it could be, for example, public static String FIRST_NAME_FIELD = "name". Then it would be more clear, both in the Constants class and at every usage, what the string "name" means.
And, of course, if you need to change "name" to "first_name" later, it's easier.
Performance wise, java tend to reuse Strings in the String pool.
Constants are usually used when you know the value won't change or must not be changed by anyone else.
For a constant you must add final to you variable declaration:
public static final String NAME="name";
Constants are more related to better coding, organization and reuse than to performance.
Related
Is it a good idea to declare all text getting used for logging as public static final from performance point of view or otherwise ?
Does it have any advantage other than readability in case one string is getting used only once ?
First, the objective part of your question: is there a performance benefit from declaring a log statement static final, i.e:
private static final String SUCCESS = "Success!";
//[...]
log.info(SUCCESS);
log.info(SUCCESS);
// versus:
log.info("Success!");
log.info("Success!");
The JLS states in section 3.10.5:
[A] string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.
So whether your string literal is declared once as a static final or appears multiple times in the source code, it will always be the same String instance, wherever it is used, and thus take up the same amount of memory, and will be accessed in exactly the same way. There will be no performance difference.
Now the other part of the question: is it a good idea? That is inherently subjective, but my opinion is that you should avoid declaring log messages as static final. Log messages add to the readability of the code, which is especially valuable when the code is being maintained by people who did not write it. For example:
log.warn(LOGIN_ERROR_OCCURRED, userId, attempt);
// compared to:
log.warn("Login failed for user {}; attempt {} of 5.", userId, attempt);
It's much quicker and easier to read the log message in the context of the code, rather than having to jump somewhere else in the code to see the full log message.
Easier internationalization and localization are possible advantages of using identifiers for string constants.
ResourceBundle bundle = ...
private final static LOGIN_ERROR_OCCURRED = bundle.getString("Login failed for user {}; attempt {} of 5");
But the benefits of i18n/L10n for log messages may be questionable.
Logging strings almost certainly should not be declared public, at least not usually. In most cases, it's better to declare constant variables for them, but sometimes you can be loose about that. Constants should appear together near the top of the class source, so for logging strings this gives a good overview of what happens in the class. It also makes it easier to find them for maintenance, like to edit out silly extraneous exclamation points. (Don't laugh; I've seen them.) I disagree that they obscure the point of log messages, unless you suck at naming variables. Which far too many people do.
A new Code Review process has been put in place and now my team must not ever declare a string as a local variable, or the commit won't pass the code review. We are now to use constants instead.
So this is absolutely not allowed, even if we're dead sure the string will never be used in any other place
String operationId = "create";
This is what should be used instead:
private static final String OPERATION_ID = "create";
While I totally agree to use constants for strings that appears +2 times in the code ... I just find it overkill to completely not have the ability to declare a string in place if it's used only once.
Just to make sure it's clear, all the following are NOT ALLOWED under any circumstances:
String div = "div1";
Catch(Exception ex){ LOGGER.log("csv file is corrupt") }
String concatenation String str = "something ...." + someVar + "something" ... we are to replace someVar with %s, declare whole thing as a global string, and then later use String.format(....)
if( name.equals("Audi" ){....}
String value = map.get("key")
Any ideas guys ? I want some strong arguments. I'm ready to embrace any stand that's backed by a good argument.
Thanks.
First, let's throw out your assumption: There's nothing inherently wrong with the approach described.
It's not about strings being used in more than one place, it's about constants being easy to find and documented, and your code being consistent.
private static final String OPERATION_ID = "create";
Really, this isn't used anywhere else? Nothing would break if I changed this to the string "beetlejuice"? If something would break, then something else is using this constant... If the "something else" happens to be a codebase in a different language, and that's why they don't share string constants-- that's the exception, not the rule. Consistency!
That said, there are a few things I would standardize in a slightly different manner, but I would still standardize them nonetheless:
I would suggest allowing string literals in the constructors of enums:
public enum Operation {
CREATE("create"),
...
}
because here, the enum is the constant that is being referenced in the code, not the string literal. Declaring the constant as an enum or as a private static final String are equivalent to me, and there's no need to do both.
Additionally, I would not use this pattern anywhere that it breaks your IDE's ability to warn you about missing strings-- For example, looking up strings from .properties files. Many IDEs will give you proper warnings when you look up a key in a .properties file that doesn't exist, but the extra level of indirection might break that depending upon how smart your IDE is.
Catch(Exception ex){ LOGGER.log("csv file is corrupt") }
This to me is a bit of a gray area - Is this an internal-only message? Are the logs only ever seen by you, the developer, or are they for a user's benefit too?
If it's only for developers of the application These probably don't need to be localized.
If you do expect the user to view the logs, then they should be externalized into a .properties file.
It is good coding style to define a constant for a value/literal when the value/literal is used multiple times.
The imposed coding style forces you to use a constant for every string literal.
The good effect of that coding style is: All string literals which really should be declared as constants are now declared as constants.
The bad implication of that coding style is: You - the developers - are not able to decide if a string literal should be defined as constant or not. This is a heavy punch.
Therefore you should raise your concerns that the good intention of the coding style does not compensate for the mistrust in your developer qualitites.
In different projects I see that some use hardcoded strings and others constants.
I cannot find an answer as to which is better for RAM memory, use constants or hardcoded?
i.e.
#SerializedName(value = Constants.Annotation.PICTURE_ID)
private int pictureID;
or
#SerializedName(value = "picture_url")
private String url;
I think they are the same. Java compiler replaces all the constants with the value of it. In this case, PICTURE_ID will be replaced with "picture_url". So the two methods you suggested are the same at compile time. So it makes no difference when you run it.
However, that is not the end of the story. When you use strong literals, it's called early binding. This binds the value at code writing time. When you want to change all the same string literals at different places, you need to change it one by one. If you use constants however, you just need to change the constant value. Thus, the latter increases maintainability and it is recommended.
My perception for defining string constants in Java is that one should define a string constant, when the same string is used at multiple places. This help in reducing typo errors, reduce the effort for future changes to the string etc.
But how about string that are used at a single place. Should we declare string constant even in that case.
For eg. Logging Some counter (random example).
CounterLogger.addCounter("Method.Requested" , 1)
Is there an advantage of declaring constant rather than using raw string?
Does the compiler does any optimization?
Declaring constants can improve your code because they can be more descriptive. In your example
CounterLogger.addCounter("Method.Requested" , 1)
The method parameter "Method.Requested" is quite self describing but the 1 is not making this a constant would make this example more readable.
CounterLogger.addCounter("Method.Requested" , INITIAL_VALUE)
The way I see it, Strings can be used in one of two ways:
As properties / keys / enumerations - or in other words, as an internal representation of another Objects/states of your application, where one code component writes them, and another one reads them.
In UI - for GUI / console / logging display purposes.
I Think it's easy to see how in both cases it's important to avoid hard-coding.
The first kind of strings must (if possible) be stored as constants and exposed to whichever program component that might use them for input/output.
Displayed Strings (like in your Logger case) are strings that you might change somewhere in the future. Having them all stored as static final fields in a constants-dedicated class can make later modifications much easier, and help avoid duplicates of similar massages.
Regarding the optimization question - as others have already answered, I believe there's no significant difference.
Presumably, you'll want to write a unit test for whichever method contains that line of code. That unit test will need access to that String value. If you don't use a constant, you'll have the String repeated twice, and if you have to change it in the future, you'll have to change it in both places.
So best to use a constant, even though the compiler is not going to do any helpful optimisations.
In my view in your case is fine. If you cant see any advantage in declaring it as a constant dont do it. To support this point take a look at Spring JdbcTemplate (I have no doubt that Spring code is a good example to follow) it is full of String literals like these
Assert.notNull(psc, "PreparedStatementCreator must not be null");
Assert.notNull(action, "Callback object must not be null");
throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
but only two constants
private static final String RETURN_RESULT_SET_PREFIX = "#result-set-";
private static final String RETURN_UPDATE_COUNT_PREFIX = "#update-count-";
Iterestingly, this line
Assert.notNull(sql, "SQL must not be null");
repeats 5 times in the code nevertheless the authors refused to make it a constant
I use around 1000 properties associated with a specific java.util.Properties which is backed by a file. The main reason for the file is to change them without recompiling the program and to allow users to adjust their according to their taste.
Some of the properties are used only in one place in the code, but there are some properties that are used several times in different segments of code and even different classes.
I have recently got the habit of declaring all those properties that are used as a String constants, usually in a seperate interface like this:
public interface AnimalConstants {
public static final String WEIGHT_PROPERTY = "weight";
public static final String RUNNING_SPEED_PROPERTY = "speedInKph";
public static final String HOURS_OF_SLEEP_A_DAY_PROPERTY = "sleepHrs";
...
}
When a class need to access some of the animal properties, I just implement this interface and I have access to all those property constants declared. When I need a specific property I just use the corresponding constant, without thinking what is its exact name (since abbreviations are used often) and, what is more important, the risk of mistyping a property name is eliminated this way. Another advantage is that if I later choose to rename a property to make it more clear to the advanced user who configures those properties), I just need to change that name in the interface where that property constant is declared (and of course the property file), so no need to "search and replace" the entire project. Finally, I can easily check whether the property is being used or not; I just comment it, compile the code and see if there is an error.
However, in spite of all these advantages, I am curious what are the disadvantages of this approach. What interests me the most is the following:
What impact has this approach (1000 String constants) on the String pool? Or they are created on-demand when I access those constants? Does this prevent other Strings from being cached in the String pool?
What is the performance cost of this approach compared to the one where I use hard-coded String constants, is it the same (neglecting the cost of accessing field)? Does the String pool behave similarly or a lot different?
What's the average memory increase with this approach, are all those String constants kept in memory all the time?
Any good comment/observation is welcome.
Static fields are are initialized during the initialization phase during class loading.
But if a primitive type or a String is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a compile-time constant. If the value of the constant in the outside world changes (for example, if it is legislated that pi actually should be 3.975), you will need to recompile any classes that use this constant to get the current value.
This is when String Literals for unique string's will be created which are defined as values of constants.
But it is similar as loading constants from resources in Properties object (writing code for same). Constants definitely consume memory.
String pool behavior wont change.
Some thought on design approach:
It is very easy to put all configuration constants in a class, then refer to them throughout the app.
To change the static configuration constants you modify the source and recompile.
What if at some point in future, your program needs maintain more than one configuration, or to alternate between configurations as it processes different files, or even runs one thread with one configuration and another thread with a different configuration. You won’t be able to use that technique.
So for better designs you store constants which never change as static constants in Class definition.These are loaded as soon as Class is loaded in memory.
In other case which i described earlier (Resource loading) you keep these in various properties files which can be loaded in JAVA Properties object. Examples for such cases can be JDBC connection related information, etc...
1) What impact has this approach (1000 String constants) on the String pool?
Declaring property names as String constants is the right decision. But there will be no change in the 'String Literal Pool'. When multiple instances of the same literal present, all of them are simply linked to same item in the literal pool (provided String constructor is not used).
2) they are created on-demand when I access those constants?
String literals are added to 'String Literal Pool' during class loading.
3) Does this prevent other Strings from being cached in the String pool?
No.
4) What is the performance cost of this approach compared to the one where I use hard-coded String constants, is it the same (neglecting the cost of accessing field)? Does the String pool behave similarly or a lot different?
It is the same.
5) What's the average memory increase with this approach, are all those String constants kept in memory all the time?
I have already answered. :)
Additional notes
a) Constants interface is a Java anti-pattern. Please avoid it.
b) You must read this Javaranch article.