#java #performance #class #constants #final
#java #Производительность #класс #константы #Финал
Вопрос:
Есть ли какая-либо разница в производительности и / или любых других преимуществах, которые мы можем получить при использовании ключевого слова final с constant utility class. [ Этот класс содержит только статические конечные поля и закрытый конструктор, чтобы избежать создания объекта]
public class ActionConstants {
private ActionConstants() // Prevents instantiation
{ }
public static final String VALIDFIRSTLASTNAME = "[A-Za-z0-9.\s] ";
public static final String VALIDPHONENUMBER = "\d{10}";
...
...
}
Только класс diffrence is становится окончательным
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}";
...
...
}
Мне хотелось бы знать, есть ли какие-либо преимущества в использовании final и каков правильный способ определения класса для констант.
Ответ №1:
Никакой пользы. Это ничего не меняет в отношении ваших static final
атрибутов.
Когда класс становится окончательным, компилятор может воспользоваться этим для переопределяемых методов (статические методы не могут быть переопределены, в лучшем случае они скрывают их в унаследованных классах).
Поскольку класс является final , компилятор знает, что ни один из его методов не может быть переопределен. Таким образом, он может вычислять случаи, когда код полиморфизма не нужно генерировать (т. Е. код, который находит правильную «версию» переопределяющего метода в соответствии с экземпляром объекта во время выполнения). Следовательно, возможна оптимизация.
Если вы хотите сделать класс действительно уникальным, вы можете использовать что-то вроде этого:
public enum ActionConstants {
INSTANCE;
public static final int cte1 = 33;
public static final int cte2 = 34;
}
И если вас вообще не интересует экземпляр класса, просто поместите все свои константы в интерфейс.
Комментарии:
1. Не уверен, что вам нужно
INSTANCE
. У меня было бы перечисление без экземпляров.2. Обычно «Интерфейсы следует использовать только для определения типов. Они не должны использоваться для экспорта констант.»
3. @Peter Lawrey Вам нужно указать хотя бы одно значение для перечисления, я вызвал свой ЭКЗЕМПЛЯР, но это может быть что угодно…
4. @JVerstry, Где сказано, что вам нужен минимум один? Вы пробовали удалить ЭКЗЕМПЛЯР и поместить просто
;
5. @JVersty, Некоторые сочли бы перечисление без экземпляров взломом. 😉
Ответ №2:
Если вы ищете улучшенную производительность, вам лучше предварительно скомпилировать свои шаблоны, такие как
public static final Pattern VALIDFIRSTLASTNAME = Pattern.compile("[A-Za-z0-9.\s] ");
public static final Pattern VALIDPHONENUMBER = Pattern.compile("\d{10}");
Использовать final или нет — это очень мало по сравнению со стоимостью использования регулярного выражения.
Комментарии:
1. На самом деле использование интерфейса для определения констант считается антишаблоном en.wikipedia.org/wiki/Constant_interface
2. @Вспомогательный метод, я согласен, но я не вижу, где упоминается интерфейс. 😉
Ответ №3:
Реальной выгоды нет, но это подтверждает ваше ожидание, что ничто не расширяет ваш класс. В долгосрочной перспективе это может упростить, например, поиск в вашем коде по всем видам использования констант, поскольку они гарантированно будут XXX.abc, а не YYY.abc, где YYY расширяет XXX.
Ответ №4:
Вам следует избегать использования «классов для констант». Это означает плохой ddesign. Поместите константы в классы, которые с ними работают. Также избегайте использования общедоступных констант. Это должно быть исключением, а не обычной практикой.
Комментарии:
1. Как правило, но не всегда , это лучшая практика. Бывают случаи, когда существуют некоторые стандартные константы, которые на самом деле не принадлежат ни одному классу, который их использует.
2. Не могли бы вы, пожалуйста, привести пример?
3. Подумайте о математических элементах, например, вы не хотели бы определять их в каждом месте, где вы их используете.
4. Я упоминал, что есть некоторые исключения из этого правила. Но шаблон регулярного выражения — это не тот случай.
Ответ №5:
Использование класса для констант является необычным. В большинстве случаев используется интерфейс. Это было бы доступно через ActionConstants.VALIDFIRSTLASTNAME
:
public interface ActionConstants {
static final String VALIDFIRSTLASTNAME = "[A-Za-z0-9.\s] ";
static final String VALIDPHONENUMBER = "\d{10}";
...
}
Начиная с Java 5, вы также можете использовать перечисление. Перечисление может иметь члены или расширенную функциональность.
Во втором примере используется простой элемент (здесь используется общий подход, если у вас разные типы констант, иначе вы также можете использовать String
элемент):
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();
В последнем примере используется расширенная функциональность, когда все константы имеют один и тот же тип.
Вы можете использовать его как 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();
}
}
Обе версии допускают использование статического импорта.
Комментарии:
1. похоже на отрицательный голос за этот ответ, есть ли какие-либо проблемы с этим подходом.