问题
Is the any difference in performance and/or any other benefits we can get when using final keyword with constant utility class. [ This class contains only static final fields and private constructor to avoid object creation]
public class ActionConstants {
private ActionConstants() // Prevents instantiation
{ }
public static final String VALIDFIRSTLASTNAME = "[A-Za-z0-9.\\s]+";
public static final String VALIDPHONENUMBER = "\\d{10}";
...
...
}
Only diffrence is class is made final
public final class ActionConstants {
private ActionConstants() // Prevents instantiation
{ }
public static final String VALIDFIRSTLASTNAME = "[A-Za-z0-9.\\s]+";
public static final String VALIDPHONENUMBER = "\\d{10}";
...
...
}
I like to know, is there any benefits there in using final and what is the correct way to define class for constants.
回答1:
There is no benefit. It does not change anything regarding your static final
attributes.
When a class is made final, the compiler can take advantage of this for overridable methods (static methods cannot be overriden, at best, they hide those one in inherited classes).
Since the class is final, the compiler knows none of its method can be overriden. So, it can compute cases where polymorphism code does not need to be generated (i.e., the code finding the right 'version' of the overriding method according to the object instance at runtime). Hence, an optimization is possible.
If you want to make a class truly unique, you can use something like this:
public enum ActionConstants {
INSTANCE;
public static final int cte1 = 33;
public static final int cte2 = 34;
}
And if you are not interested in a class instance at all, just put all your constants in an interface.
回答2:
If you are looking for improved performance you are better off pre-compiling your patterns like
public static final Pattern VALIDFIRSTLASTNAME = Pattern.compile("[A-Za-z0-9.\\s]+");
public static final Pattern VALIDPHONENUMBER = Pattern.compile("\\d{10}");
Using a final or not is, very small compared to the cost of using a regular expression.
回答3:
There is no real benefit, but it does enforce your expectation that nothing extends your class. That might make it easier in the long term to, for example, search your code for all uses of the constants since they will be guaranteed to be XXX.abc and not YYY.abc where YYY extends XXX.
回答4:
You should avoid using "classes for constants". It means a bad ddesign. Place constants in classes that operate with them. Avoid using public constants as well. It should be exception, not a normal practice.
回答5:
To use a class for constants is uncommon. In most cases an interface is used. This would be accessible by ActionConstants.VALIDFIRSTLASTNAME
:
public interface ActionConstants {
static final String VALIDFIRSTLASTNAME = "[A-Za-z0-9.\\s]+";
static final String VALIDPHONENUMBER = "\\d{10}";
...
}
Since Java 5 you can also use an enum. An enum can have members or extended functionality.
The second example uses a simple member (here with a generic approach if you have different constant types, else you can also use a String
member):
public enum ActionConstants {
FIRSTLASTNAME("[A-Za-z0-9.\\s]+"),
PHONENUMBER("\\d{10}");
private final Object value;
private ActionConstants(Object value) {
this.value= value;
}
@SuppressWarnings("unchecked")
public <T> T getValue() {
return (T)value;
}
}
String value = ActionConstants.FIRSTLASTNAME.getValue();
The last example uses extended functionality when all constants are of the same type.
You can use it like ActionConstants.PHONENUMBER.isValid("0800123456")
:
public enum ActionConstants {
FIRSTLASTNAME("[A-Za-z0-9.\\s]+"),
PHONENUMBER("\\d{10}");
private final Pattern pattern;
private ActionConstants(String pattern) {
this.pattern = Pattern.compile(pattern);
}
public void isValid(String value) {
return pattern.matcher(value).matches();
}
}
Both versions allow the use of static imports.
来源:https://stackoverflow.com/questions/6134149/final-keyword-in-constant-utility-class