Whether I am right or wrong about this I am not sure but SonarLint gives me countless warnings about the repeated use of certain strings.
As a result, I created a constants file purely for Strings in a module that is already accessed in every other module in the project.
My thought was if we are continually being warned about this. It's probably creating each of these strings multiple times and temporarily increasing memory.
(It's a web app, generating JSON and XML with many frequently repeated terms such as "identity" or "community")
The question I am wondering is, my IDE (IntelliJ) seems to just keep adding the following line:
import static com.*****.*****.resources.Constants.*
Instead of:
import static com.*****.*****.resources.Constants.PARAM_NAME_HASEMAIL;
import static com.*****.*****.resources.Constants.PARAM_NAME_HASSMS;
import static com.*****.*****.resources.Constants.PARAM_NAME_CMD;
Bearing in mind the file is currently small with maybe around 100 constants, but that figure will eventually reach 250.
First of all my question is, which of the imports is more efficient, just import the file, import each required constant, or it doesn't matter that much (max will definitely be 250 constants in the file)
The second question I have is, is this worth the effort (easy but grunt work)?
One example is:
data.has(PARAM_NAME_OPTIN)
data.remove(PARAM_NAME_OPTIN);
data.put(PARAM_NAME_OPTINTYPE, Coupon.OPTIN_MODE_SINGLE_OPTIN);
The above is in maybe 3 or 4 locations in different files.
The definitions of those 2 constants are:
public static final String PARAM_NAME_OPTIN = "optin";
public static final String PARAM_NAME_OPTINTYPE = "optInType";
The worst offender is below. It is in every single method that makes a call to the backend from the front end (following an ajax request in the browser):
json.put(PARAM_NAME_CMD, "Coupon.doSearchCouponEntriesByCoupon");
json.put(PARAM_NAME_APPID, PARAM_NAME_CAMPAIGN);
json.put(PARAM_NAME_COMMUNITYID, session.getAttribute(PARAM_NAME_COMMUNITYID));
json.put(PARAM_NAME_IDENTITYID, session.getAttribute(PARAM_NAME_IDENTITYID));
Again the definitions are:
public static final String PARAM_NAME_APPID = "applicationId";
public static final String PARAM_NAME_CMD = "command";
public static final String PARAM_NAME_CAMPAIGN = "*****campaign";
public static final String PARAM_NAME_COMMUNITYID = "communityId";
public static final String PARAM_NAME_IDENTITYID = "identityId";
I have starred the package names to try to obscure the company. Even if this doesn't really share any IP or secrets, better safe than sorry.
I appreciate any feedback you give (good or bad).
Additional info: one of the files I am doing the import manually for each one used currently has 22 imports for those constants.
I guess if the number reaches such heights, then maybe I should switch to the * instead? Or does it still have memory implications?
My thought was, if we are continually being warned about this. It's probably creating each of these strings multiple times and temporarily increasing memory. (It's a web app, generating JSON and XML with many frequently repeated terms such as "identityId" or "communityId")
That's actually wrong. At runtime, all string literals are interned by the class loader. So, if you have 20 examples of "identityId" in many different classes, at runtime you will have only one String object that represents all copies of the literal. (This is NOT an implementation detail. The JLS guarantees this behavior.)
The real reason for the SonarLint warnings is that having multiple copies of the same string literal is liable to cause maintenance problems. If you want to change "identityId" to "identityID", you have 20 separate places to change it ... and the IDE is not going to be a lot of help.
First of all my question is, which of the imports is more efficient, just import the file, import each required constant, or it doesn't matter that much
It has zero impact on runtime performance, and the impact on compilation speeds is most likely insignificant.
The most significant impact of the different styles of import is on the readability of your source code, and that is largely a matter of opinion.
The second question I have is, is this worth the effort?
That is definitely a matter of opinion .... in the examples that you presented.
However, if the strings were messages for users to read, then you may need to internationalize them. If that is the case, then you will be better of storing the strings in (for example) a properties file ... and use different files depending on the user's preferred language.
Finally, assuming that you do decide to use String constants (which is a good idea), I wouldn't recommend putting them all into a big "constants" class. Define them in ordinary classes and interfaces, according to their purpose.
Repeated use of the same literal string does not create a memory overhead, since all literal strings in Java source code are interned. SonarLint warns you not because of memory inefficiency, but because of the risk of errors and reduced readability.
The problem with your proposed solution using static import of the whole class, is that you won't know where the constants came from when you later read the source code where they are used. That's why it's generally preferred to "static import" named fields. But if you have 250 such constants, you might not want to add 250 static import lines to your file.
Instead of naming your constants PARAM_NAME_APPID etc., put them in a class called ParamNames. Then you "static import" the class name so you can see where it's come from, and the constants have self-explanatory names:
static import package.name.ParamNames;
....
xxx = ParamNames.APP_ID;
Refactor the Constants class into a property file.
It then contains your constants like this
PARAM_NAME_APPID=applicationId
you can load it using
Properties constants = new Properties();
try (FileReader reader = new FileReader("constants.properties")) {
constants.load(reader);
}
Related
Can I call a static method of another class without using the class name (in the same package)? There are similar questions but all answers there use class names.
Yes. But, you would need to import it. Specifically, import static. Like,
import static com.package.OtherClass.someMethod;
Then you can call someMethod(String) like
someMethod("Like that");
It is possible using static imports, however I would like to caution you against using them. Static imports obfuscate where the code lives which makes it harder to understand the code structure. Combined with * imports, humans can no longer determine (without spending a lot of time) the source of the method, although IDEs can.
An example of why it could be bad: let's say you want to see how a problem was solved in a open source project, to get ideas for your own project. And you know what? You can view the code as HTML online. Things are going great! You view the java file you want to see. Then there is this peculiar method "foo". So you search the page for "foo" and there is exactly 1 match (the one you are looking at). There are multiple import static blabla.* lines at top, so that is a dead end. You download the source. Next you do a full text search on the entire project for "foo(" => 5000 matches in 931 files. At which point you no longer have a choice other than loading the project into an IDE if you want to grok the code. You would not have to do any of that if the author would have made it clear where the method lives to begin with. Now, if you do not use * imports, then finding the class is a 2 step process, so it is not nearly as bad. I personally don't use static imports at all. With short yet meaningful names, I find that the explicit type is preferable.
I dislike static imports, because it breaks OO (well, not technically, just conceptually). But this is a personal opinion and the vast majority disagrees with me. So feel free to form your own. The following post has a great discussion on when (not) to use static imports:
What is a good use case for static import of methods?
Yes it's possible to call static method of a class without using Class reference by using static import.
ex:
import static java.lang.Math.*;
public class compute{
public double getSqrt(double n){
return sqrt(n)
}
}
It's preferable to use this way if static methods are used in lot of places in the class.
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
In the past I often used "import static" construct in Java classes. Recently I realized that instead of
import static my.pack.A.MY_CONSTANT;
you can use
import my.pack.A;
public class B {
private static final MY_CONSTANT = A.MY_CONSTANT;
}
The most obvious advantages of this approach are:
You can use refactoring in Eclipse to easily strip out all long constant expressions like A.B.C.CONSTANT.ANOTHER_ONE.TOO_LONG from your code without messing with static imports (which are not so quick to master in Eclipse)
You can give any name to any expression, which may be more meaningful in the current context.
For example:
private static final PAYMENT_TYPE = PaymentType.CASH;
...
calculateSomething(amount, PAYMENT_TYPE);
instead of
import static my.pack.PaymentType.CASH
...
calculateSomething(amount, CASH);
and also this is more easy to refactor, if the default PaymentType value changes to CREDIT_CARD.
My question is: are there any downsides of this approach compared to static imports or can it be used everywhere instead?
My only concern for now is the resulting compiled .class file, which is probably different for the two described approaches. So performance and memory usage may theoretically suffer.
I think the only downside is you have more code where you assign one constant to another constant. Other than that there should be no difference. Performance and memory shouldn't matter, you'll likely have more references back to the same constant pool entries. Even if it created separate constant pool entries it would take a lot of them to make a difference.
Being able to give good names to constants might be a very good thing, in cases where it isn't feasible to rename the original entries.
It is mostly a matter of taste, but the official docs recommend using the static version sparingly, especially with a wildcard. The main downside of static import is that it pollutes your namespace by added all the static members to it. In your above example, it should be about what you think it more readable for your code. Resist the urge to do "import package.*" unless you really want all the static members of package.
It should not effect your compiled code -- it is merely provides a shorthand access to the same constant.
We have a huge projects based on an old jdk 1.4. We have migrated the web app to JDK 1.6 but still lot of inefficient practices and bad design exist in the code.
On of the major pain point huge java classes 2500+ lines of code in single java file. So many files like these.
In an attempt to refactor the classes I had started off by removing constants and putting constants in different Constants.java file. but since there are so many constants through-out the application, the constants file has the risk of growing to humongous proportions.
I would appreciate feedback on what strategy are developers adopting to keep code clean and maintainable.
Keep your constants in the class they are related to, don't feel obligated to extract them. It may clean up the code of the class, but mixing unrelated constants in a file is not an improvement.
Keep things related together.
And also you can convert them to Enums when possible/useful (but that can require some refactoring).
Putting all the Constants in a single file is a terrible idea! Especially the uber-Constant anti-pattern where all the Constants are in an Interface that every class has to implement. 10 ways to Sunday terrible! This was a bad idea when people started doing it back in the early 1990's before Java! It is definitely a bad idea in 2012!
It means you are mingling lots of un-related information and creating un-needed dependencies everytime you import this uber-Constants file. Things that go together should be together in an Enum or at least in the Class that uses them as arguments to its methods so that when they are changed you know how to do an impact analysis easily.
Imagine Color constants mixed in with DaysOfTheWeek constants mixed in with other business domain constants and there will be hundreds if not thousands of these things in a single file. How can that ever be considered a good idea? In every non-contrived case, an Enum that is a public inner member of a Class is a better solution.
It also means you have a single flat namespace to try and create names that don't conflict, then they aren't obvious what they belong to and how they should be used. This is never a positive exercise.
When designing and refactoring you should always:
Strive for high cohesion, this means keep related things as close together as possible.
Strive for loose coupling this means don't let un-related things leak into other un-related scopes.
Strive for self-documenting maintainable code, dozens or hundreds of private static final String/int declarations all mixed together doesn't fit this definition by anyone's standard!
In 2012 C-style constants are a poor solution when you now have Enum as a tool, you should be focused on converting as many of these groups of Constants to Enum wherever possible. Enum is type safe and can have other attributes and properties and behaviors attached to it to make them intelligent. That is the path to go down.
Just putting constants in a Constant.java file doesn't make sens in my opinion (it just move the problem away). But sometimes I use to regroup them to clear the things and use several files to regroup them : DatabaseConstants.java, GraphicConstants.java and so on...
and of course, using enums can be useful too (and best practice).
edit : to be precise, I actually work with Java ME application, so it's just a way to "mimic" the enums I can't have, with a "controlled vocabulary" in abstract classes (I miss all the Java EE features...)
For someone who is visiting this page.
If you don't want to maintain multiple constant files, below is the better way to organize.
public interface Constants {
public static final String CREATE_USER = "createUser";
// Nested Interface.
public interface ProjectConstants {
public static final String CREATE_PROJECT = "createProject";
public static final String INVALID_SESSION = "Invalid Session";
// As you know they are implicity public static final.
}
}// Accessed as:
Constants.ProjectConstants.CREATE_PROJECT
Updates:
As a best practice, its better to use Class.(See comments. . Thanks keplerian.)
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
I'd like to share a design pattern for constants i've seen a few years ago that maybe can help.
Start by creating a BaseConstant file. This will hold all your global constants that all packages could use.
Now in each subpackage of your app create a Constants file that will only be related to the subpackage . So if you had . a subpackage called Login only put constants related to login there. But the key is to extend off of BaseConstants. this way you get to see all the global constants in the IDE chooser but when you open the file you only see your package constants. that being said i think constant files can get really heavy and duplicate values and hard to read.
Here is what i mean ..
public class BaseConstants{
public static final String GLOBAL1= "GLOBAL string";
public static final String GLOBAL2= "another GLOBAL string";
}
Now in all your other packages create a files like this:
class MyPackageConstants extends BaseConstants{
public static final String LOCAL1 = "local String"
public static final String LOCAL2= "ANOTHER LOCAL string";
}
in your IDE when you type "MyPackageConstants." you should see all the constants for the entire application.
I've never heard of putting all of the constants to a single java file. The best way is to put the constants accossiated with the classes in themselves, but name them with capital letter and underscores like this one: EXAMPLE_CONSTANT
Have you tried using Enums for all of your constants? I've been told it is the preferred way since Java 1.5.
http://docs.oracle.com/javase/1.5.0/docs/guide/language/enums.html
I think that if you have multiple java files over 2500 LOCs, the decision where to put the constants should be the least of your problems. You should form a clear picture of how the restructured system will look like.
This is probably much harder then deciding where to stick the constants and other syntactic considerations but needs to be done first nevertheless.
I am designing a java API(not an API exactly) in my office which will contain 4000+ constants. So all the teams can use them directly. Initially i thought to create their classes according to their type and create their static objects into a separate class. So anybody any use them directly.
But after reading need of static variable, i afraid it could be a problem of creating so many static variables. Is there any alternate?
*After me whoever will join this project can also add a constraint in my Constant class without caring of performance. There is a possibility that many of the constants will be used rarely.
*Every member of Constant class will represent a class which will have its own behavior. It might be the part of some inheritance tree further. So using enum might not be a good idea.
You want to create a location where some 4000+ constants will live. there's the possibility that users of this class may add constants (possibly at runtime)?. T
Concern about the memory issues of statics is misplaced. If you need 4000 values, they're going to have to live somewhere, right?
If people will be adding values at runtime, this sounds like a singleton Map or Properties (which is really just a kind of map anyway) of some kinds. People often use dependency injection frameworks like Spring or Guice to manage this sort of thing.
If you just mean adding compile constants, you can make them all static. You'd probably want to make them static final as well, they'll be compiled inline.
It's very likely that 4000 constants is a very bad idea. Where I've seen systems with large numbers of constants (>100, even) defined in one place, what usually happens is that people forget the definitions of them and end up using their own variants , which sort of defeats the purpose (for example, I've worked on a system with 100's of SQL queries defined in a "Queries" class. Of course people immediately ignore it as it's more of a bother to look up if the exact query you need is in there than to roll your own. The class eventually grew to something like 1500 queries, many exact duplicates and many unused, most used once. Utterly pointless). I can imagine exceptions where you wouldn't "lose" things with naming conventions, but unless you've got a use case like that this seems like a really bad idea.
Breaking out your constants into enums gives you type-safe references. It also makes things conceptually easier to deal with. Compare:
-
public class Constants {
String WORK_ADDRESS;
String WORK_PHONE;
String HOME_ADDRESS;
String HOME_PHONE;
}
with
public enum ADRESS{ WORK, HOME }
public enum PHONE { WORK, PHONE }
Which would you rather work with?
Performance is highly unlikely to be the problem with this design. RAM is cheap. (Cue the usual quote: Premature optimization is the root of all evil.)
On the other hand, I'm not quite sure how any client developer can remember and use 4000+ constants. Can you give us an idea what sort of object this is?
You may, depending on details you haven't given us, find it useful to collect constants into enums. Stateless enums can be easier to understand than public static final variables if there are some natural groupings you can take advantage of.
What happens when you allocate in static is that it surely won't be freed in the runtime of your app.
so what ?
if you don't create them static then they'll be duplicated through every instance of your classes.
what you don't want to do is to set static huge amounts of data such as images or GUI
an image takes up a lot more than a few fields;
4000 constants of surely int (4 octet) = 16000 octets not even the size of an icon ^^
I would point out hte Javadoc to prove my point
http://download.oracle.com/javase/1.4.2/docs/api/constant-values.html#java.awt.event.KeyEvent.CHAR_UNDEFINED
this is the KeyEvent decleration in Java, check the out declarations ^^
Unless you are creating large arrays or very long strings, 4000 data values isn't going to be a lot of memory. I think that post you cited was talking about much larger amounts of data.
Another approach is to read the values from a preferences file.
Perhaps the constants be modularized into a collection of classes, so the more rarely used ones will be loaded only on demand.