Константы в Java на примерах
«Constant (константа)» – слово в английском языке, относящееся в основном к «ситуации, которая не меняется». Это одна из фундаментальных концепций программирования в Java, и у нее нет каких-либо специальных предпосылок или концепций, которые необходимо знать перед изучением, кроме базовых навыков программирования.
Константы в Java используются, когда необходимо реализовать «статическое» или постоянное значение для переменной. Язык программирования напрямую не поддерживает константы. Чтобы сделать любую переменную ею, мы должны использовать модификаторы static и final.
Синтаксис
static final datatype identifier_name = constant;
- Модификатор static делает переменную доступной без загрузки экземпляра ее определяющего класса.
- Последний модификатор делает переменную неизменной.
Причина, по которой мы должны использовать как статические, так и конечные модификаторы, заключается в том, что:
- Когда мы объявим переменную «var» только как статическую, все объекты одного класса смогут получить доступ к этому ‘var’ и изменить его значения.
- Когда мы объявляем переменную только как final, для каждого отдельного объекта будет создано несколько экземпляров одного и того же значения константы, и это неэффективно / нежелательно.
- Когда мы используем как static, так и final, тогда «var» остается статичным и может быть инициализирован только один раз, что делает его надлежащей константой, которая имеет общую ячейку памяти для всех объектов своего содержащего класса.
Пример
static final int MIN_AGE = 18;
Допустим, нам нужно определить, кто имеет право на получение постоянных водительских прав в группе людей. Мы уже знаем, что минимальный возраст для получения постоянных водительских прав составляет 18 лет.
Поэтому вместо того, чтобы просить пользователя ввести минимальный возраст для сравнения, мы объявляем идентификатор MIN_AGE как постоянное целое число со значением 18.
import java.util.*; public class DrivingLicense < public static void main(String [] args)< Scanner sc = new Scanner(System.in); static final int MIN_AGE = 18; //Minimum age requirement int[] list = new int[5]; System.out.println("Enter the age of people:"); for(int i=0;i<5;i++)< list[i] = sc.nextInt(); >System.out.println("Result for eligibility:"); for(int i=0;i<5;i++) < if(list[i] >= MIN_AGE) System.out.println(i + " is Eligible"); else System.out.println(i + " is Not Eligible"); > > >
Зачем нужны?
Константы делают вашу программу более легкой для чтения и понимания, когда ее читают другие. Использование их также повышает производительность, поскольку константы кэшируются как JVM, так и вашим приложением.
Статические и окончательные модификаторы
- Статический модификатор в основном используется для управления памятью.
- Это также позволяет переменной быть доступной без загрузки какого-либо экземпляра класса, в котором она определена.
- Последний модификатор означает, что значение переменной не может измениться. Как только значение назначено переменной, другое значение не может быть переназначено той же переменной.
С помощью модификатора final типы данных Primitive, такие как int, float, char, byte, long, short, double, Boolean, можно сделать неизменяемыми / неизменяемыми. Вместе, как мы поняли ранее, эти модификаторы создают постоянную переменную.
Общий синтаксис
public static final int MAX_VALUE = 1000;
Это соглашение использовать заглавную букву имени переменной, которую мы хотим объявить как константу. Если мы сохраним спецификатор доступа для постоянной переменной как частный, то его значения не могут быть изменены в этом классе.
Если мы оставим спецификатор доступа общедоступным для постоянной переменной, то его значения можно изменить в любом месте программы.
Пример 1
В этом примере мы использовали перечисление как enum Apple . Идентификаторы Jonathan, GoldenDel, RedDel, Winesap и Cortland называются константами перечисления.
Каждый из них неявно объявлен как публичный статический финальный член Apple. Переменная перечисления может быть создана как другая примитивная переменная. Он не использует «новый» для создания объекта.
‘ap’ имеет тип Apple, единственные значения, которые могут быть назначены (или могут содержать), являются значениями, определенными перечислением.
Все перечисления имеют два предопределенных метода: values() и valueOf(). Синтаксис этих встроенных методов:
public static enum-type [] .values() public static enum-type.valueOf (String str)
Метод values() дает массив, который состоит из списка констант перечисления. Метод valueOf() дает константу перечисления, значение которой соответствует строке, переданной в str.
Пример 2
enum Season < WINTER, SPRING, SUMMER, FALL; >class EnumExample < public static void main(String[] args) < for (Season s : Season.values()) System.out.println(s);//will display all the enum constants of Season Season s = Season.valueOf("WINTER"); System.out.println("S contains " + s);//output: S contains WINTER >>
В приведенном выше примере мы использовали два встроенных метода перечисления.
Public class constant java
Вопрос глуппый но задам. Сборщик мусора не сходит сума при работе с immutable? Наример нам приходится в программе таскать ‘с собой’ масивы строк и паралельно в них менять значения. Это жесть какая нагрузка на железо.
public static void main(String[] args)
Вывод: I love Java I love Java Честно говоря, не понимаю, что удивительного в этом коде? Код же выполняется сверху вниз. А тут четверть статьи этому посвятили) Я так понимаю, что если я в конце в коде напишу: System.out.println(str1);, то вывод будет: I love Java I love Python Или я что-то не так понял?
Ведьмаку заплатите – чеканной монетой, чеканной монетой, во-о-оу Ведьмаку заплатите, зачтется все это вам
Всё что я должен понять из этой статьи: final для класса — класс нельзя наследовать, final для метода — метод нельзя переопределять, final для переменной — нельзя изменять первое присвоенное значение (сразу присваивать не обязательно), имя пишется капсом, слова через нижний пробел. Объекты всех классов обёрток, StackTrace, а также классы, используемые для создания больших чисел BigInteger и BigDecimal неизменяемые. Таким образом, при создании или изменении строки, каждый раз создаётся новый объект. Кратко о String Pool: Строки, указанные в коде литералом, попадают в String Pool (другими словами «Кэш строк»). String Pool создан, чтобы не создавать каждый раз однотипные объекты. Рассмотрим создание двух строковых переменных, которые указаны в коде литералом (без new String).
String test = "literal"; String test2 = "literal";
При создании первой переменной, будет создан объект строка и занесён в String Pool. При создании второй переменной, будет произведён поиск в String Pool. Если такая же строка будет найдена, ссылка на неё будет занесена во вторую переменную. В итоге будет две различных переменных, ссылающихся на один объект.
Мало примеров и в целом, недосказано. Под конец вскользь упомянут String Pool, а что это не объясняется. Статья озаглавлена какFinal & Co, а по факту пару примеров по строкам, ну, такое. Это называется собирались пироги печь, а по факту лепёшки лепим. В любом случае, конечно, спасибо за труд. Но, гораздо лучше про строки написано здесь: Строки в Java (class java.lang.String). Обработка строк в Java. Часть I: String, StringBuffer, StringBuilder (более детальная статья на Хабре).
Получается мы не можем создать поле какого нибудь класса не константой public static final String name = «Амиго»; обязательно только так? => public static final String CHARACTER_NAME = «Амиго»; или можно написать и так и так?
«В прошлых лекциях мы видели простой пример наследования: у нас был родительский класс Animal, и два класса-потомка — Cat и Dog» ?! А была лекция о наследовании?! Может быть я где-то пропустил, поделитесь ссылкой, пожалуйста 🙂
Константы и интернационализация
При работе программа опирается в вычислениях или вводе-выводе используется не только переменные, но и явно прописанные константы. Допустим Вы обрабатываете финансовые данные и по ходу кода несколько раз выводите результаты (пусть в консоль) примерно таким образом:
System.out.println("Итоговое количество =" + countLoans); . String strCount = "Итоговое количество :" + loans.calc(); . System.out.println(strCount + strSumDesc);
- Нарушение принципа DRY (Don’t repeat yourself — не повторяй).
Дублирование текста и, как следствие, увеличение размеров скомпилированного кода. Также при этом возможны описки. - Нарушение принципа KISS (keep it simple stupid — делайте вещи проще).
В случае необходимости изменения такого рода констант придется прошерстить весь код. - Каждое изменение константы потребует перекомпиляции кода.
- Ввод мультиязычности потребует (при таком построении кода) много дополнительных конструкций к каждой такой константе.
и применяем примерно как System.out.println(Constants.MSG_TOTAL_AMOUNTCOUNT_DEPARTMENT + » confs/config.properties»); PROPS.load(fis); fis.close(); > catch ( IOException e) < log.error(e.getMessage()); >MSG_TOTAL_AMOUNT = PROPS.getProperty(«msg.total.amount»); COUNT_DEPARTMENTS = Integer.parseInt(PROPS.getProperty(«count.departments»)); . > >
Осталось разобраться с интернационализацией. Сделаем так, чтобы в static блоке происходила загрузка нужно файла properties . Для этого будем работать с ResourceBundle . Отметим, что из ResourceBundle стандартными методами можно считывать значения ключей, но не устанавливать их. Поэтому по прежнему храним в отдельном Properties (config.properites) файле параметры, не имеющие отношение к интернационализации (к тому же некоторые из низ возможно менять по ходу действия программы). Например, язык интерфейса. Удобный интерфейс IDEA нам поможет. Создаем его: Добавляем нужные языки: В структуре проекта для IDEA отображается как: Наполняем содержимым:
public class Constants < public static final int COUNT_DEPARTMENTS; public static final String MSG_TOTAL_AMOUNT; public static final Properties PROPS; public static final ResourceBundle UI_LANGUAGE; static < Logger log = LogManager.getLogger(Constants.class); PROPS = new Properties(); try< fis = new FileInputStream("confs/config.properties"); PROPS.load(fis); fis.close(); >catch ( IOException e) < log.error(e.getMessage()); >if (PROPS.getProperty("ui.language").equalsIgnoreCase("RUS")) UI_LANGUAGE = ResourceBundle.getBundle("messages", CharsetControl.RUS); else UI_LANGUAGE = ResourceBundle.getBundle("messages", CharsetControl.ENG); MSG_TOTAL_AMOUNT = UI_LANGUAGE.getString("msg.total.amount"); COUNT_DEPARTMENTS = Integer.parseInt(PROPS.getProperty("count.departments")); . > >
- Перегонять кириллические символы в ESCAPE-последовательности \uxxxx через native2ascii
- Помочь Properties передав ему необходимый ResourceBundle.Control , в котором нам необходимо перегрузить метод (код нашел на просторах интернета + немного модифицировал).
import java.io.*; import java.net.URL; import java.net.URLConnection; import java.nio.charset.Charset; import java.security.*; import java.util.*; public class CharsetControl extends ResourceBundle.Control < public static final CharsetControl UTF_8 = new CharsetControl("utf8"); public static final CharsetControl RUS = new CharsetControl("cp1251"); public static final Locale ENG = new Locale("en","GB"); private Charset charset; public CharsetControl(String charset) < this(Charset.forName(charset)); >public CharsetControl(Charset charset) < this.charset = charset; >public Charset getCharset() < return charset; >@Override public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException < String bundleName = toBundleName(baseName, locale); ResourceBundle bundle = null; if (format.equals("java.class")) < try < ClassbundleClass = (Class)loader.loadClass(bundleName); if (ResourceBundle.class.isAssignableFrom(bundleClass)) < bundle = bundleClass.newInstance(); >else < throw new ClassCastException(bundleClass.getName() + " cannot be cast to ResourceBundle"); >> catch (ClassNotFoundException e) < >> else if (format.equals("java.properties")) < final String resourceName = toResourceName(bundleName, "properties"); final ClassLoader classLoader = loader; final boolean reloadFlag = reload; InputStream stream = null; try < stream = AccessController.doPrivileged( new PrivilegedExceptionAction() < public InputStream run() throws IOException < InputStream is = null; if (reloadFlag) < URL url = classLoader.getResource(resourceName); if (url != null) < URLConnection connection = url.openConnection(); if (connection != null) < connection.setUseCaches(false); is = connection.getInputStream(); >> > else < is = classLoader.getResourceAsStream(resourceName); >return is; > >); > catch (PrivilegedActionException e) < throw (IOException) e.getException(); >if (stream != null) < try < bundle = new PropertyResourceBundle(new InputStreamReader(stream, getCharset())); >finally < stream.close(); >> > else < throw new IllegalArgumentException("unknown format: " + format); >return bundle; > >