Сокрытие и затенение переменных в Java

В Java можно объявлять переменные в классе, методе, блоке или конструкторе. В зависимости от варианта объявления, у переменной могут быть разные области видимости в программе, а сама переменная может относиться к статическому или нестатическому типу в зависимости от того, где она объявлена.
Основываясь на этих критериях, можно разделить все переменные в Java на следующие типы: локальные переменные, переменные экземпляра и переменные класса. Затенение (shadowing) и сокрытие (hiding) переменных происходит, когда оказываются одноименными две переменные в разных областях видимости (в локальной и глобальной области видимости, в родительских и дочерних классах). При таком сценарии используется значение той переменной, которая находится во внутренней области видимости, так как она затемняет/скрывает значение той переменной, что находится во внешней области видимости.
Введение
Рассмотрим нижеприведенный пример, где определяется две переменные с именем id. Можно предположить, что следующая программа выбросит ошибку, так как мы объявили две переменные с одним и тем же именем id. Но, к счастью, никаких ошибок не возникнет, а мы получим вывод 5678. Хотя обе переменные и имеют одно и то же имя id, они объявляются в разных областях видимости: одна в глобальной, а другая в локальной.
Переменная id в глобальной области видимости доступна из любой точки внутри класса, тогда как переменная id в локальной области видимости доступна только из метода main(). Вывод равен 5678, поскольку здесь происходит затенение переменной: переменная id внутри метода main() «заслоняет» глобальную переменную id и использует собственное значение.
class Main < // глобальная область видимости String ; public static void main(String[] args) < // локальная область видимости String ; System.out.println(id); >>
Вывод
5678
Чтобы разобраться с затенением и сокрытием переменных, сначала нужно изучить различные типы переменных, имеющиеся в Java: как и где они объявляются, какова их область видимости и применения, т.д. Все переменные Java можно подразделить на три типа.
- Локальные переменные
- Переменные экземпляра
- Глобальные переменные
Локальные переменные
Переменные, объявляемые внутри метода, блока или конструктора, называются локальными. Область видимости локальной переменной ограничена пределами того метода, блока или конструктора, в которой она создана. Локальные переменные создаются, когда программа переходит к выполнению метода, блока или конструктора, и уничтожаются, как только выполнение закончено. Локальные переменные нельзя объявлять как статические.
public int findSum(int[] arr) < // локальная переменная int sum = 0; for (final int j : arr) < sum += j; >return sum; >
В этом примере sum – это локальная переменная, так как она объявлена внутри метода findSum(), и извне этого метода к ней обратиться нельзя.
Переменные экземпляра
Переменные, объявляемые внутри класса, но вне метода называются переменными экземпляра. Переменные экземпляра не объявляются как статические. Переменные экземпляра создаются при создании объекта и уничтожаются при уничтожении объекта.
class Student < // переменная экземпляра private final String name; public Student(String name) < this.name = name; >public String getName() < return this.name; >>
В данном примере name – это переменная экземпляра, поскольку она объявляется внутри класса, но вне метода. Новая переменная name создается для всех вновь создаваемых объектов Student.
Переменные класса
Переменные, объявляемые как статические внутри класса, но вне метода, называются переменными класса. Переменные класса объявляются как статические.
В каждом класса любая переменная класса может существовать всего в одном экземпляре, независимо от того, в каком количестве создаются объекты. Переменные класса создаются при запуске программы и уничтожаются, когда программа завершается. Переменные класса также называются статическими.
class Variable < // переменная класса static int classVariable; int instanceVariable; public Compare() < int localVariable; >>
В данном примере classVariable – это переменная класса, так как она объявляется внутри класса, но вне метода, и при этом объявляется как статическая. Переменная classVariable совместно используется всеми созданными объектами Variable.
Что такое затенение переменных?
Затенение переменных происходит, когда переменная во внутренней области видимости объявляется с таким же именем, с каким уже существует переменная во внешней области видимости. В данном случае переменная во внутренней области видимости затемняет (маскирует) переменную во внешней области видимости. Затенение переменных происходит даже в том случае, когда обе одноименные переменные относятся к разным типам данных.
Пример затемнения переменных
В примере, приведенном ниже, у нас две переменные с именем name. Одна из них находится внутри метода print() (внутренняя область видимости), а другая внутри класса Student (внешняя область видимости). Метод print выводит имя Steve Rogers, а не Tony Stark, поскольку имя локальной переменной внутри метода print() (это внутренняя область видимости) затемняет переменную экземпляра name, находящуюся внутри класса Student (внешняя область видимости). Поэтому на экран выводится значение затеняющей переменной – той, что находится в методе print().
class Student < // переменная экземпляра String name = "Tony Stark"; public void print() < // локальная переменная String name = "Steve Rogers"; System.out.println(name); >> public class Main < public static void main(String[] args) < Student student = new Student(); student.print(); >>
Вывод
Steve Rogers
Затенение локальными переменными
Затенение локальными переменными происходит, когда локальная переменная (во внутренней области видимости) затемняет переменную экземпляра (во внешней области видимости).
class A < // переменная экземпляра int x = 1; public void display() < // локальная переменная int x = 2; System.out.println(x); System.out.println(this.x); >> public class Main < public static void main(String[] args) < A a = new A(); a.display(); >>
Вывод
В данном примере у нас две переменных (одна внутри метода display(), а другая внутри класса A), которые объявлены с одним и тем же именем x. При выводе значения той x, что находится в методе display(). На экран выводится 2, так как локальная переменная x внутри метода display() затемняет переменную экземпляра x внутри класса A.
Затенение аргументом метода
Затенение аргументом метода происходит, когда параметр метода (внутренняя область видимости) затемняет переменную экземпляра (внешняя область видимости).
class A < // instance variable int x = 1; // method parameter public void display(int x) < System.out.println(x); System.out.println(this.x); >> public class Main < public static void main(String[] args) < A a = new A(); a.display(2); >>
Вывод
В данном примере параметр метода display() и переменная экземпляра класса A имеют одинаковое имя x. Выводя значение того x, что находится внутри метода display(), видим на экране 2, так как параметр x метода display() затемняет переменную экземпляра x, находящуюся в классе A.
Что такое сокрытие переменной?
Сокрытие переменной происходит в случае, когда у переменной, объявленной в дочернем классе, имя такое же, как и у переменной, объявленной в родительском классе.
Напротив, затенение переменной происходит в случае, когда переменная во внутренней области видимости является одноименной переменной во внешней области видимости. Переменные из дочернего класса обычно скрывают переменные родительского класса при такой одноименности. Сокрытие переменной происходит даже в том случае, когда обе одноименные переменные относятся к разным типам данных.
Пример сокрытия переменных
class Parent < String name = "ParentClass"; public void display() < System.out.println(name); >> class Child extends Parent < String name = "ChildClass"; @Override public void display() < System.out.println(name); >public void displayParent() < System.out.println(super.name); >> public class Main < public static void main(String[] args) < Child child = new Child(); child.display(); child.displayParent(); >>
Вывод
ChildClass ParentClass
В данном примере показано, что переменная name в классе Child скрывает переменную name в классе Parent. Когда вызывается метод отображения в классе Child, он выводит на экран ChildClass. Ключевое слово super должно использоваться для доступу к переменной name в классе Parent.
Сокрытие в случае со статическими переменными
Статическое сокрытие происходит между двумя одноименными переменными, одна из которых относится к родительскому классу, а другая – к дочернему, причем, если перед обеими в качестве префикса стоит ключевое слово static. Статические переменные также называются переменными класса.
class Parent < static String ; static String name = "ParentClass"; public void displayName() < System.out.println(name); >public void displayId() < System.out.println(id); >> class Child extends Parent < static int static String name = "ChildClass"; @Override public void displayName() < System.out.println(name); >@Override public void displayId() < System.out.println(id); >> public class Main < public static void main(String[] args) < Parent parent = new Parent(); Child child = new Child(); parent.displayId(); parent.displayName(); child.displayId(); child.displayName(); >>
Вывод
1 ParentClass 2 ChildClass
В данном примере и в классе Parent, и в классе Child есть две переменные класса с именами id и name. Хотя, переменные дочернего класса являются одноименными переменным родительского класса, методы displayId и displayName из дочернего класса выводят данные, относящиеся именно к этому классу. Здесь переменные класса Child скрывают переменные класса Parent. Сокрытие затрагивает даже переменную id, которая в родительском и дочернем классе является одноименной, но при этом в первом и втором случае соответствует разным типам.
Сокрытие нестатических переменных
Сокрытие нестатических переменных происходит, когда две переменные (одна в родительском классе, одна в дочернем) объявляются с одинаковым именем и при этом не имеют ключевого слова static в качестве префикса. Нестатические переменные также называются переменными экземпляра.
class Parent < String name = "ParentClass"; public void displayName() < System.out.println(name); >> class Child extends Parent < String name = "ChildClass"; @Override public void displayName() < System.out.println(name); >> public class Main < public static void main(String[] args) < Parent parent = new Parent(); Child child = new Child(); parent.displayName(); child.displayName(); >>
Вывод
ParentClass ChildClass
В данном примере как у класса Parent, так и у класса Child есть нестатическая переменная name. Переменная name в классе Child скрывает переменную name в родительском классе. Когда мы выводим на экран ту переменную name, что относится к методу displayName() класса Child, мы получаем ChildClass, а не ParentClass. Дело в том, что переменная name в классе Child скрывает значение той name, что находится в классе Parent, и использует собственное значение.
Сокрытие переменной – это не то же самое, что переопределение метода
Переопределение метода – это возможность, при которой дочерний класс меняет ту реализацию метода, которую получил из родительского класса, собственной реализацией, а при сокрытии переменной реализация просто прячется.
class Parent < public void print() < System.out.println("I am Parent"); >> class Child extends Parent < @Override public void print() < System.out.println("I am Child"); >> public class Main < public static void main(String[] args) < Parent parent = new Parent(); Child child = new Child(); Parent childAsParent = new Child(); parent.displayName(); child.displayName(); childAsParent.displayName(); >>
Вывод
I am Parent I am Child I am Child
В данном примере класс Child переопределяет реализацию метода print из класса Parent (выводит I am Parent) собственной реализацией (выводит I am Child).
При сокрытии переменные дочернего класса скрывают только переменные родительского класса. С другой стороны, при переопределении методы дочернего класса заменяют методы родительского класса. Рассмотрим приведенный ниже пример, где объект childAsParent типа Parent указывает на объект типа Child.
class Parent < public String name = "ParentClass"; public void displayName() < System.out.println(name); >> class Child extends Parent < public String name = "ChildClass"; @Override public void displayName() < System.out.println(name); >> public class Main < public static void main(String[] args) < Parent childAsParent = new Child(); System.out.println(childAsParent.name); childAsParent.displayName(); >>
Вывод
ParentClass ChildClass
При сокрытии переменных переменные дочернего класса скрывают переменные родительского класса. Так что, когда мы обращаемся к переменной по ссылке из родительского класса, которая держит дочерний объект, осуществляется доступ к переменной родительского класса. Вот почему childAsParent.name выводит ParentClass.
При переопределении методы дочернего класса заменяют методы родительского класса. Так что, когда мы обращаемся к методу по ссылке из родительского класса, которая держит дочерний объект, происходит доступ к методу дочернего класса. Вот почему childAsParent.displayName() выводит ChildClass.
Как получить доступ к скрытой или затемненной переменной?
Доступ к затемненной переменной
Локальная переменная затемняет переменную экземпляра, если они одноименные. Ключевое слово this следует использовать для доступа к затемненной переменной экземпляра. В нижеприведенном примере инструкция System.out.println(this.name) выводит значение (Tony Stark), то есть, значение затемненной переменной экземпляра.
class Student < // переменная экземпляра String name = "Tony Stark"; public void print() < // локальная переменная String name = "Steve Rogers"; System.out.println(name); // выводит локальную переменную System.out.println(this.name); // выводит переменную экземпляра >> public class Main < public static void main(String[] args) < Student student = new Student(); student.print(); >>
Вывод
Steve Rogers Tony Stark
Доступ к скрытой переменной
Переменная дочернего класса скрывает переменную родительского класса, если они одноименные. Ключевое слово super следует использовать для доступа к скрытой переменной родительского класса. В нижеприведенном примере инструкция System.out.println(super.name) выводит значение (ParentClass) скрытой переменной экземпляра, относящейся к родительскому классу.
class Parent < String name = "ParentClass"; public void display() < System.out.println(name); >> class Child extends Parent < String name = "ChildClass"; @Override public void display() < System.out.println(name); System.out.println(super.name); >> public class Main1 < public static void main(String[] args) < Child child = new Child(); child.display(); >>
Вывод
ChildClass ParentClass
Разница между затенением и сокрытием переменных
Затенение переменной
Сокрытие переменной
Затенение переменной происходит, когда одноименными являются локальная переменная и переменная экземпляра в одном и том же классе
Сокрытие переменной происходит, когда переменная из дочернего класса одноименная переменной родительского класса
Затенение переменной происходит внутри класса
Сокрытие переменной происходит между дочерним и родительским классом
Заключение
- Затенение переменной происходит, когда переменная во внутренней области видимости объявляется с тем же именем, что и переменная из внешней области видимости. Переменная из внешней области видимости затемняет переменную из внутренней области видимости.
- Затенение локальной переменной происходит, когда локальная переменная во внутренней области видимости затемняет переменную экземпляра во внешней области видимости.
- Затенение аргументом метода происходит, когда параметр метода затемняет переменную экземпляра.
- Для доступа к затемненной переменной экземпляра используется ключевое слово this.
- Сокрытие переменной происходит, когда переменная, объявленная в дочернем классе, имеет то же имя, что и переменная, объявленная в родительском классе.
- К скрытой переменной из родительского класса можно обратиться при помощи ключевого слова super.
- Сокрытие переменных – не то же самое, что переопределение метода, поскольку при сокрытии переменные дочернего класса просто прячут переменные родительского класса. В свою очередь, при переопределении метода дочерний класс заменяет реализации методов из родительского класса собственными реализациями.
- Блог компании Издательский дом «Питер»
- Программирование
- Java
- Проектирование и рефакторинг
- ООП
Как сделать глобальную переменную на всю программу
Может глупый вопрос так-как в интернете много похожего, но у меня немного другой вопрос.
Как мне получать одну и ту же переменную через несвязанные классы?
Ну вот пример:
Есть два класса — Variables, Runner и Loader.
В первом классе стоит Random 1-9 и надо получить одно и то же число в 2 и 3 классе.
Лучшие ответы ( 1 )
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Как сделать одну глобальную переменную
Есть многофайловый проект. К примеру 5 файлов(5 "H" файлов+для них 5 "срр" файлов, пускай в каждом.

Как лучше сделать глобальную переменную?
Интернет совсем пустой в плане глобальных переменных на с++ Задача следующая: 1. Нужно создать.

Как в многофайловом проекте сделать глобальную переменную?
имеется проект из 100500 файлов: main.cpp — тело программы, и прочие *.h и *.cpp файлы. в main’е.
Как реализовать глобальную переменную?
Здравствуйте товарищи. есть как бы глобальная переменная int currpos = new int; currpos = 0;.
2479 / 1930 / 484
Регистрация: 17.02.2014
Сообщений: 9,207
Distemi, в main классе завести поле?
Регистрация: 23.12.2019
Сообщений: 12
Ну мне надо сделать зарегистрировать в Main другой класс для регистрирований событий Bukkit событий, но надо иметь 4 переменные HashMap, которые имеют одни и те же данные в других классах.
![]()
2484 / 1037 / 354
Регистрация: 11.08.2017
Сообщений: 3,184

Сообщение было отмечено Distemi как решение
Решение
Сообщение от Distemi 
следовательно майнкрафт)))
А так да, статик поля, причем можно для этого отдельно завести класс, только вот игра активно использует мультипоток, поэтому могут быть проблемы в сфере threadsafe если надо будет менять эту переменную
2479 / 1930 / 484
Регистрация: 17.02.2014
Сообщений: 9,207
Distemi, а так?
Кликните здесь для просмотра всего текста
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
public class Helper { static int[] n = new int[1]; public static void main(String[] args) { n[0] = 11; A a = new A(n); B b = new B(n); System.out.printf("%d, %d\n", a.getX(), b.getY()); n[0] = 1111; System.out.printf("%d, %d\n", a.getX(), b.getY()); } } class A { int[] x; public A(int[] x) { this.x = x; } public int getX() { return x[0]; } } class B { int[] y; public B(int[] y) { this.y = y; } public int getY() { return y[0]; } }
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь
Как объявить глобальную переменную?
Угораздило установить Офис2003. :-/ неужели нельзя больше использовать необъявленные.
Как задать глобальную переменную?
Как задать глобальную переменную которая будет работать на всех формах проги? Заранее спасибо.

Как объявить глобальную переменную
При объявление Public ничего не происходит Public Sub Form1_Load(ByVal sender As System.Object.
Как обьявить глобальную переменную
Как объявить глобальную переменную Есть несколько *CPP* и *.h* файлы. Надо объявить переменную.

Как объявить глобальную переменную
Вот код /* * Created by SharpDevelop. * User: admin * Date: 30.06.2014 * Time: 18:36 .
Как описать глобальную переменную?
Объявляю глобальную переменную в модуле формы Public flag as Integerно из других модулей её не.
8. Java – Типы переменных, объявление и инициализация
Переменная предоставляется нам именем хранения, чтобы нашей программой можно было манипулировать. Каждая переменная в Java имеет конкретный тип, который определяет размер и размещение её в памяти; диапазон значений, которые могут храниться в памяти; и набор операций, которые могут быть применены к переменной.
Необходимо объявить все переменные, прежде чем их использовать. Ниже показана основная форма объявления:
тип данных переменная [ = значение], [переменная [= значение], . ] ;
Чтобы объявить более чем одну переменную указанного типа, можно использовать список с запятыми в качестве разделителей.
Ниже приведены примеры объявления переменной и инициализации в Java:
int a, b, c; // Объявление трех целых a, b, и c. int a = 10, b = 10; // Пример инициализации. byte b = 22; // Инициализация переменной b типа byte. double pi = 3.14159; // Объявление и присвоение величины пи. char a = 'a'; // Переменной a типа char присваивается значение 'a'.
В этом уроке рассмотрим различные типы переменных, доступных в языке Java. Существует три типа переменных:
- локальные переменные;
- переменные экземпляра;
- статические переменные или переменные класса.
Локальные переменные в Java
- Локальные переменные объявляются в методах, конструкторах или блоках.
- Локальные переменные создаются, когда метод, конструктор или блок запускается и уничтожаются после того, как завершиться метод, конструктор или блок.
- Модификаторы доступа нельзя использовать для локальных переменных.
- Они являются видимыми только в пределах объявленного метода, конструктора или блока.
- Локальные переменные реализуются на уровне стека внутри.
- В Java не существует для локальных переменных значения по умолчанию, так что они должны быть объявлены и начальное значение должны быть присвоено перед первым использованием.
Пример
«age» – локальная переменная, определяется внутри метода «pupAge()» и области её действия ограничивается только этим методом.
public class Test < public void pupAge()< int age = 0; age = age + 7; System.out.println("Возраст щенка: " + age); >public static void main(String args[]) < Test test = new Test(); test.pupAge(); >>
Будет получен следующий результат:
Возраст щенка: 7
Пример без инициализации
Пример использования «age» без инициализации. Программа выдаст ошибку во время компиляции.
public class Test < public void pupAge()< int age; age = age + 7; System.out.println("Возраст щенка: " + age); >public static void main(String args[]) < Test test = new Test(); test.pupAge(); >>
Это приведёт к следующему сообщению об ошибке во время компиляции:
Test.java:4:variable number might not have been initialized age = age + 7; ^ 1 error
Переменные экземпляра
- Переменные экземпляра объявляются в классе, но за пределами метода, конструктора или какого-либо блока.
- Когда для объекта в стеке выделяется пространство, создается слот для каждого значения переменной экземпляра.
- В Java переменные экземпляра создаются тогда, когда объект создан с помощью ключевого слова «new» и разрушаются тогда, когда объект уничтожается.
- Переменные содержат значения, которые должны ссылаться более чем на один метод, конструктор или блок, или на основные части состояния объекта, которые должны присутствовать на протяжении всего класса.
- Переменные экземпляра могут быть объявлен на уровне класса, до или после использования.
- Модификаторы доступа могут быть предоставлены для переменных экземпляра.
- Переменные экземпляра в Java являются видимыми для всех методов, конструкторов и блоков в классе. Как правило рекомендуется сделать их private (уровень доступа). Однако можно сделать их видимыми для подклассов этих переменных с помощью модификаторов доступа.
- Переменные экземпляра имеют значения по умолчанию. Для чисел по умолчанию равно 0, для логических – false, для ссылок на объект – null. Значения могут быть присвоены при объявлении или в конструкторе.
- Переменные экземпляра в Java могут быть доступны непосредственно путем вызова имени переменной внутри класса. Однако в статических методах и различных класса (когда к переменным экземпляра дана доступность) должны быть вызваны используя полное имя – ObjectReference.VariableName.
Пример
import java.io.*; public class Employee < // Переменная экземпляра открыта для любого дочернего класса. public String name; // Переменная salary видна только в Employee. private double salary; // Имя переменной присваивается в конструкторе. public Employee (String empName)< name = empName; >// Переменной salary присваивается значение. public void setSalary(double empSal) < salary = empSal; >// Этот метод выводит на экран данные сотрудников. public void printEmp() < System.out.println("имя: " + name ); System.out.println("зарплата:" + salary); >public static void main(String args[]) < Employee empOne = new Employee("Олег"); empOne.setSalary(1000); empOne.printEmp(); >>
Программа будет будет производить следующий результат:
имя: Олег зарплата: 1000.0
Переменные класса или статические переменные в Java
- Переменные класса, также известные в Java как статические переменные, которые объявляются со статическим ключевым слово в классе, но за пределами метода, конструктора или блока.
- Там будет только одна копия каждой статической переменной в классе, независимо от того, сколько объектов создано из него.
- Статические переменные или переменные класса в Java используются редко, кроме когда объявляются как константы. Константы — переменные, которые объявлены как public/private, final и static. Константы никогда не меняются от первоначального значения.
- В Java статические переменные создаются при запуске программы и уничтожаются, когда выполнение программы остановится.
- Видимость похожа на переменную экземпляра. Однако большинство статических переменных объявляются как public, поскольку они должны быть доступны для пользователей класса.
- Значения по умолчанию такое же, как и у переменных экземпляра. Для чисел по умолчанию равно 0, для данных типа Boolean – false; и для ссылок на объект – null. Значения могут быть присвоены при объявлении или в конструкторе. Кроме того, они могут быть присвоены в специальных блоках статического инициализатора.
- Статические переменные могут быть доступны посредством вызова с именем класса ClassName.VariableName.
- При объявлении переменных класса как public, static, final, имена находятся в верхнем регистре. Если статические переменные такими не являются, синтаксис такой же, как у переменных экземпляра и локальных.
Пример
import java.io.*; public class Employee < // salary(зарплата) переменная private static private static double salary; // DEPARTMENT(отдел) – это константа public static final String DEPARTMENT = "Разработка "; public static void main(String args[])< salary = 1000; System.out.println(DEPARTMENT+"средняя зарплата: "+salary); >>
Это будет производить следующий результат:
Разработка средняя зарплата: 1000
Примечание: для получения доступа из внешнего класса, константы должны быть доступны как Employee.DEPARTMENT.
В предыдущих материалах не раз упоминались модификаторы доступа. В следующем уроке мы подробно их рассмотрим.
Оглавление
- 1. Java – Самоучитель для начинающих
- 2. Java – Обзор языка
- 3. Java – Установка и настройка
- 4. Java – Синтаксис
- 5. Java – Классы и объекты
- 6. Java – Конструкторы
- 7. Java – Типы данных и литералы
- 8. Java – Типы переменных
- 9. Java – Модификаторы
- 10. Java – Операторы
- 11. Java – Циклы и операторы цикла
- 11.1. Java – Цикл while
- 11.2. Java – Цикл for
- 11.3. Java – Улучшенный цикл for
- 11.4. Java – Цикл do..while
- 11.5. Java – Оператор break
- 11.6. Java – Оператор continue
- 12. Java – Операторы принятия решений
- 12.1. Java – Оператор if
- 12.2. Java – Оператор if..else
- 12.3. Java – Вложенный оператор if
- 12.4. Java – Оператор switch..case
- 12.5. Java – Условный оператор (? 🙂
- 13. Java – Числа
- 13.1. Java – Методы byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()
- 13.2. Java – Метод compareTo()
- 13.3. Java – Метод equals()
- 13.4. Java – Метод valueOf()
- 13.5. Java – Метод toString()
- 13.6. Java – Метод parseInt()
- 13.7. Java – Метод Math.abs()
- 13.8. Java – Метод Math.ceil()
- 13.9. Java – Метод Math.floor()
- 13.10. Java – Метод Math.rint()
- 13.11. Java – Метод Math.round()
- 13.12. Java – Метод Math.min()
- 13.13. Java – Метод Math.max()
- 13.14. Java – Метод Math.exp()
- 13.15. Java – Метод Math.log()
- 13.16. Java – Метод Math.pow()
- 13.17. Java – Метод Math.sqrt()
- 13.18. Java – Метод Math.sin()
- 13.19. Java – Метод Math.cos()
- 13.20. Java – Метод Math.tan()
- 13.21. Java – Метод Math.asin()
- 13.22. Java – Метод Math.acos()
- 13.23. Java – Метод Math.atan()
- 13.24. Java – Метод Math.atan2()
- 13.25. Java – Метод Math.toDegrees()
- 13.26. Java – Метод Math.toRadians()
- 13.27. Java – Метод Math.random()
- 14. Java – Символы
- 14.1. Java – Метод Character.isLetter()
- 14.2. Java – Метод Character.isDigit()
- 14.3. Java – Метод Character.isWhitespace()
- 14.4. Java – Метод Character.isUpperCase()
- 14.5. Java – Метод Character.isLowerCase()
- 14.6. Java – Метод Character.toUpperCase()
- 14.7. Java – Метод Character.toLowerCase()
- 14.8. Java – Метод Character.toString()
- 15. Java – Строки
- 15.1. Java – Метод charAt()
- 15.2. Java – Метод compareTo()
- 15.3. Java – Метод compareToIgnoreCase()
- 15.4. Java – Метод concat()
- 15.5. Java – Метод contentEquals()
- 15.6. Java – Метод copyValueOf()
- 15.7. Java – Метод endsWith()
- 15.8. Java – Метод equals()
- 15.9. Java – Метод equalsIgnoreCase()
- 15.10. Java – Метод getBytes()
- 15.11. Java – Метод getChars()
- 15.12. Java – Метод hashCode()
- 15.13. Java – Метод indexOf()
- 15.14. Java – Метод intern()
- 15.15. Java – Метод lastIndexOf()
- 15.16. Java – Метод length()
- 15.17. Java – Метод matches()
- 15.18. Java – Метод regionMatches()
- 15.19. Java – Метод replace()
- 15.20. Java – Метод replaceAll()
- 15.21. Java – Метод replaceFirst()
- 15.22. Java – Метод split()
- 15.23. Java – Метод startsWith()
- 15.24. Java – Метод subSequence()
- 15.25. Java – Метод substring()
- 15.26. Java – Метод toCharArray()
- 15.27. Java – Метод toLowerCase()
- 15.28. Java – Метод toString()
- 15.29. Java – Метод toUpperCase()
- 15.30. Java – Метод trim()
- 15.31. Java – Метод valueOf()
- 15.32. Java – Классы StringBuilder и StringBuffer
- 15.32.1. Java – Метод append()
- 15.32.2. Java – Метод reverse()
- 15.32.3. Java – Метод delete()
- 15.32.4. Java – Метод insert()
- 15.32.5. Java – Метод replace()
- 16. Java – Массивы
- 17. Java – Дата и время
- 18. Java – Регулярные выражения
- 19. Java – Методы
- 20. Java – Потоки ввода/вывода, файлы и каталоги
- 20.1. Java – Класс ByteArrayInputStream
- 20.2. Java – Класс DataInputStream
- 20.3. Java – Класс ByteArrayOutputStream
- 20.4. Java – Класс DataOutputStream
- 20.5. Java – Класс File
- 20.6. Java – Класс FileReader
- 20.7. Java – Класс FileWriter
- 21. Java – Исключения
- 21.1. Java – Встроенные исключения
- 22. Java – Вложенные и внутренние классы
- 23. Java – Наследование
- 24. Java – Переопределение
- 25. Java – Полиморфизм
- 26. Java – Абстракция
- 27. Java – Инкапсуляция
- 28. Java – Интерфейсы
- 29. Java – Пакеты
- 30. Java – Структуры данных
- 30.1. Java – Интерфейс Enumeration
- 30.2. Java – Класс BitSet
- 30.3. Java – Класс Vector
- 30.4. Java – Класс Stack
- 30.5. Java – Класс Dictionary
- 30.6. Java – Класс Hashtable
- 30.7. Java – Класс Properties
- 31. Java – Коллекции
- 31.1. Java – Интерфейс Collection
- 31.2. Java – Интерфейс List
- 31.3. Java – Интерфейс Set
- 31.4. Java – Интерфейс SortedSet
- 31.5. Java – Интерфейс Map
- 31.6. Java – Интерфейс Map.Entry
- 31.7. Java – Интерфейс SortedMap
- 31.8. Java – Класс LinkedList
- 31.9. Java – Класс ArrayList
- 31.10. Java – Класс HashSet
- 31.11. Java – Класс LinkedHashSet
- 31.12. Java – Класс TreeSet
- 31.13. Java – Класс HashMap
- 31.14. Java – Класс TreeMap
- 31.15. Java – Класс WeakHashMap
- 31.16. Java – Класс LinkedHashMap
- 31.17. Java – Класс IdentityHashMap
- 31.18. Java – Алгоритмы Collection
- 31.19. Java – Iterator и ListIterator
- 31.20. Java – Comparator
- 32. Java – Дженерики
- 33. Java – Сериализация
- 34. Java – Сеть
- 34.1. Java – Обработка URL
- 35. Java – Отправка Email
- 36. Java – Многопоточность
- 36.1. Java – Синхронизация потоков
- 36.2. Java – Межпоточная связь
- 36.3. Java – Взаимная блокировка потоков
- 36.4. Java – Управление потоками
- 37. Java – Основы работы с апплетами
- 38. Java – Javadoc
Глобальные переменные в Java: когда их использовать?


Привет! В этой статье мы поговорим о глобальных переменных, об их объявлении и примерах уместного использования. Небольшое примечание: мы не будем рассматривать глобальные переменные класса, то есть те, доступ к которым есть в рамках какого-либо одного класса. Будем говорить о глобальных переменных всего приложения — тех, доступ к которым есть в рамках целого приложения.
Как создавать глобальные переменные
Глобальные переменные — это переменные, которые доступны отовсюду в приложении. Иначе говоря их область видимости — все приложение. Чтобы создать такую переменную в Java, необходимо в публичном классе создать публичную статическую переменную:
public class Example
Переменные a , b и str — стали глобальными. Мы можем получить к ним прямой доступ из других классов внутри приложения:
public class GlobalVarsDemo < public static void main(String[] args) < Example.a = 4; Example.b = 5; Example.str = "Global String variable value"; System.out.println(Example.a); System.out.println(Example.b); System.out.println(Example.str); >>
Если мы запустим метод main , то увидим следующий вывод:
4 5 Global String variable value
- переменные которые можно редактировать;
- переменные, которые можно только считывать.
public class Constants

По соглашению об именовании в ЯП Java, все константы нужно именовать в верхнем регистре, разделяя слова символом нижнего подчеркивания. Итак, мы создали константы, и теперь мы не сможем изменять их значения:Однако, мы можем считывать их значения:
public class HelloWorld < public static void main(String[] args) < System.out.println(Constants.HELLO_WORLD_STR); >>
Hello, World!
public class ConstantsDemo < public static void main(String[] args) < double r = 10; String message = String.format("Площадь круга с радиусом %f=%f", r, getCircleSquare(r)); System.out.println(message); >static double getCircleSquare(double r) < return Constants.PI * r * r; >>
Площадь круга с радиусом 10,000000=314,159265
Стоит ли использовать глобальные переменные

В интернете много статей, основной посыл которых такой: глобальные переменные — это зло, плохо и ужасно. Так ли это на самом деле? Попробуем привести плюсы и минусы глобальных переменных, чтобы каждый мог сделать вывод самостоятельно.Начнем с минусов. Представим себе приложение, в котором есть класс с глобальными переменными, доступными для чтения и редактирования. Со временем в проекте растет количество классов, количество глобальных переменных и методов, которые используют глобальные переменные, а иными словами — зависят от них. Со временем каждая глобальная переменная считывается в разных частях системы для разных целей. В разных частях системы значение переменной может обновляться. Общая картина мира данного приложения существенно усложняется, и отсюда вытекают такие минусы :
- Снижение читабельности и увеличение сложности понимания кода.
- Увеличение сложности сопровождения кода.
- Для изменения одной глобальной переменной, необходимо проанализировать весь код, чтобы не задать переменной невалидное для других частей системы значение.
- Увеличение ошибок, которые очень сложно отлаживать. Представим себе глобальную переменную, массив объектов. В одной части системы в данном массиве ожидаются например строки, а в другой части системы кто-то решил использовать числа с плавающей точкой. Вряд ли кому-то захочется в таком разбираться.
- Имена переменных могут совпасть, если вы используете в своем коде глобальные переменные, а также некоторые библиотеки, в которых в свою очередь также используются глобальные переменные. Это может привести к ошибкам как на стороне вашего приложения, так и на стороне используемой вами библиотеки.
- Увеличивается связность между различными частями системы, которые используют глобальные переменные. Стремиться нужно наоборот к слабой связанности кода. Лучше иметь много маленьких подсистем, слабо связанных друг с другом, чем одну здоровенную фиговину. Потому что мозгу легче разбираться с несколькими простыми вещами, чем с одной слишком сложной и запутанной штукой.
- Написание юнит-тестов усложняется, поскольку тесту не известно, какие глобальные переменные нужны и каким образом их необходимо проинициализировать.
- В многопоточных приложениях использование глобальных переменных разными потоками приводит к росту ошибок, которые сложно отлаживать, и к росту сложности проекта. Из-за этого необходимо настраивать доступ к таким переменным более правильно, обвешивая их синхронизациями и блокировками. В будущем это может привести к замкнутым блокировкам. Например, поток А заблокировал для своей работы переменную X, а поток B заблокировал для своей работы переменную Y, а потоку А теперь нужна переменная Y, а потоку B переменная X. В итоге, программа зависнет.
Но это все неточно. Это описание рисков, вероятность которых увеличивается с ростом проекта и ростом числа глобальных переменных в нем. Перейдем к плюсам :
- В маленьких проектах глобальные переменные — наиболее простая вещь для достижения работоспособности проекта.
- Иногда страх использования глобальных переменных приводит к еще большему усложнению проекта. Тогда программисты начинают создавать синглтоны и прибегать к прочим шаблонам проектирования.
- В программировании часто бывает нужно опираться на некоторые неизменные значения. Самое разумное — записать такие значения в виде константы, потому что только константы дают гарантию, что значение переменной не изменится со временем. Такие константы можно встретить сплошь и рядом ( Integer.MAX_VALUE , Integer.MIN_VALUE , Boolean.TRUE , Collections.EMPTY_LIST и пр.). Но программирование не ограничивается использованием стандартных библиотек. Часто бывает нужно писать какую то уникальную логику, в которой необходимо будет опираться на свои, уникальные константы. Поэтому порой использование констант (глобальных переменных, доступных только для чтения) действительно упрощает жизнь.
В целом, не стоит злоупотреблять глобальными переменными, по возможности использовать только константы. Ранее было сказано, что использовать глобальные переменные в маленьких проектах — это не плохо. Но начинающему разработчику лучше вообще их не использовать. По двум причинам:
- Все, что пишет начинающий разработчик — по сути небольшой проект. И использование в его проектах глобальных переменных приучит его к использованию глобальных переменных везде.
- Лучше научиться сначала обходиться без «запретных приемчиков». А с опытом понимание, когда такие приемчики уместно применять, придет само.