Инициализация статических членов данных. Статический блок. Инициализация массивов
Если в классе объявлен статический член данных, то он всегда существует в одном экземпляре, независимо от количества создаваемых объектов класса. Статический член данных может быть объявлен как член данных класса:
class MyClass < static int d; // статический член данных класса static float x; // статический член данных класса . >
Если статический член данных примитивного типа не инициализирован в классе, то нему присваивается значение по умолчанию. Если статический член данных есть ссылкой на объект, то нему присваивается значение null .
Ниже приведены значения по умолчанию, которые присваиваются статическим членам данных в случае отсутствия явной инициализации
static int i; // i = 0 static boolean b; // b = false static float f; // f = 0.0 static double d; // d = 0.0 static char c; // c = символ с кодом 0 static CDate objDate; // objDate = null
Если нужно осуществить явную инициализацию статического члена данных в месте его объявления, тогда это осуществляется точно так же как и для нестатического члена данных:
class MyClass < static int d = 25; // инициализация статического члена данных конкретным значением static float x = 108.35; . >
Более подробно работа со статическими членами данных в Java освещается в теме:
2. Пример инициализации статических членов данных класса. Инициализация статического члена данных с помощью метода
В примере объявляется два класса с именами CDate и CStaticData . В классе CStaticData статические члены данных класса инициализируются так же как и нестатические члены данных класса.
// инициализация статических членов данных класса public class CStaticData < // инициализация статических членов класса static int i = 2588; static boolean b = true; static float f = 3.23f; static double d = -10.2093; // инициализация статического объекта (экземпляра) класса static CDate objDate = new CDate(); // инициализация статического члена класса с помощью метода класса GetPi() static double Pi = GetPi(); // метод GetPi() класса также может быть статическим static double GetPi() < return 3.1415; > public static void main(String[] args) < CStaticData obj = new CStaticData(); obj.b = false; CStaticData.d = -10.223; > >
Как видно из примера, чтобы инициализировать статический член данных класса Pi с помощью метода GetPi() , этот метод может быть также объявлен как статический.
3. Какой порядок инициализации, если в классе объявляются статические и нестатические члены данных класса?
Если в классе объявляются статические и нестатические члены данных класса, то первыми инициализируются статические члены данных класса. После этого инициализируются нестатические члены данных класса.
Пример. Объявляется класс CDataInit , в котором в произвольном порядке инициализируются статические и нестатические члены данных класса.
public class CDataInit < // внутренние функции, которые используется при инициализации int GetInt(String s) < System.out.println("Non-static initialization of " + s); return 100; > static int GetIntStatic(String s) < System.out.println("Static initialization of " + s); return 5; > // переменные, которые должны быть инициализированы - объявлены в произвольном порядке int i1 = GetInt("i1"); static int si1 = GetIntStatic("si1"); int i2 = GetInt("i2"); int i3 = GetInt("i3"); static int si2 = GetIntStatic("si2"); int i4 = GetInt("i4"); static int si3 = GetIntStatic("si3"); public static void main(String[] args) < CDataInit obj = new CDataInit(); > >
После объявления объекта класса CDataInit выводятся следующие строки:
Static initialization of si1 Static initialization of si2 Static initialization of si3 Non-static initialization of i1 Non-static initialization of i2 Non-static initialization of i3 Non-static initialization of i4
Как видно из приведенного выше результата, первыми инициализируются статические члены данных.
4. Что такое статический блок? Общая форма
Статический блок – это специальная конструкция, которая помогает сгруппировать несколько действий, предназначенных для инициализации статических членов данных.
Общая форма статического блока:
static < // операции, которые инициализируют статические члены класса // . >
В классе статический блок выглядит приблизительно следующим образом:
class ClassName < . static < // инициализация статических членов данных класса // . > . >
5. Пример использования статического блока
В классе CDataInit объявляется статический блок, в котором инициализируются статические переменные a , b , c , d .
public class CDataInit < static int a, b, c, d; // инициализация с помощью статического блока static < a = 1; b = 2; c = 3; d = 4; > public static void main(String[] args) < CDataInit obj = new CDataInit(); int t; // проверка t = obj.a; // t = 1 t = obj.b; // t = 2 t = obj.c; // t = 3 t = obj.d; // t = 4 > >
6. Сколько раз вызывается статический блок? В каких случаях вызывается статический блок?
Статический блок вызывается только один раз в одном из двух случаев:
- при первом создании объекта этого класса;
- при первом обращении к статическим членам этого класса.
Пример. Пусть задан класс CDataInit , который содержит объявление статических членов с именами a , b , c , d .
public class CDataInit < static int a, b, c, d; // инициализация с помощью статического блока static < a = InitMethod("a color: #0000ff;"> b = InitMethod("b color: #0000ff;"> c = InitMethod("c color: #0000ff;"> d = InitMethod("d color: #993366;"> static int InitMethod(String s) < System.out.println(s + "100"); return 100; > public static void main(String[] args) < // создание объекта - вызывается статический блок CDataInit obj = new CDataInit(); CDataInit obj2 = new CDataInit(); // второй раз статический блок не вызывается > >
В результате выполнения этого кода, будет выведен результат:
a = 100 b = 100 c = 100 d = 100
Как видно, в функции main() создается два объекта, а инициализированные данные выводятся только один раз. Это подтверждает правило, которое гласит: статические члены данных инициализируются в классе только один раз.
Если в функции main() вместо строки
CDataInit obj = new CDataInit();
ввести код обращения к статической переменной, например
то также будет вызван статический блок инициализации, но только один раз.
7. Инициализация массивов в классе. Как в классе инициализировать массив значениями?
В языке Java массив в классе может быть инициализирован одним из двух способов:
- непосредственным присваиванием значений массива. В этом случае в фигурных скобках задается набор значений, которые присваиваются массиву;
- присваиванием ссылки на другой массив. В этом случае присваивается ссылка на другой массив с помощью оператора присваивания ‘=’ .
8. Пример инициализации одномерных массивов в классе
Объявляется класс CInitArray , в котором объявляются массивы a , x и ссылки на них с именами b , y .
public class CInitArray < // инициализация массива в классе // вариант 1 - непосредственная инициализация значениями int[] a = < 1, 2, 4, 9, -8, 13, 7 >; // в массиве 7 элементов double x[] = < -1.33, 2.905, 1.308, 10.301, 8 >; // в массиве 5 элементов // вариант 2 - присваивание ссылки int[] b = a; // массив b ссылается на одно и то же место что и массив a double[] y = x; // массив y ссылается на x public static void main(String[] args) < CInitArray M = new CInitArray(); int len; // проверка длины каждого из массивов len = M.a.length; // len = 7 len = M.x.length; // len = 5 // проверка конкретных значений массивов int d; double f; d = M.a[3]; // d = 9 f = M.x[2]; // f = 1.308 d = M.b[3]; // d = 9 len = M.b.length; // len = 7 f = M.y[0]; // f = -1.33 len = M.y.length; // len = 5 // изменение в ячейке массива a приводит к изменению в ячейке массива b и наоборот M.a[2] = 100; d = M.b[2]; // d = 100 M.b[0] = -11; d = M.a[0]; // d = -11 // так же, изменение в ячейке массива x приводит к изменению в ячейке массива y, и наоборот M.x[3] = 1.75; f = M.y[3]; // f = 1.75 M.y[1] = -3.22; f = M.x[1]; // f = -3.22 > >
Массивы a , x инициализируются начальными значениями с использованием фигурных скобок. После этого длина массивов есть неизменной.
Массивы b и y класса инициализируются значениями, которые есть в массивах a , x . Вернее, массивы b и y ссылаются на ячейки массивов a , x .
В функции main() тестируется длина каждого массива и значения элементов массива. Длину каждого массива можно определить с помощью свойства length .
9. Пример инициализации двумерного массива в классе
Инициализация двумерного массива осуществляется точно также как и одномерного.
public class CInitArray < // инициализация двумерного массива в классе // вариант 1 - непосредственная инициализация значениями // объявляется двумерный массив aa размером 4*3 int[][] aa = < < 1, 2, 5 >, < 3, 8, 9 >, < 4, 11, -7 >, < 2, 2, 0 >>; // вариант 2 - присваивание ссылки int[][] bb = aa; // bb ссылается на aa public static void main(String[] args) < CInitArray M = new CInitArray(); int len, d; // проверка длин массивов len = M.aa.length; // len = 4 - количество строк len = M.aa[0].length; // len = 3 - количество столбиков в строке с индексом 0 // проверка значений d = M.aa[0][2]; // d = 5 // изменение в ячейке массива a приводит к изменению в ячейке массива b, и наоборот M.aa[0][2] = 13; d = M.bb[0][2]; // d = 13 M.bb[1][0] = 25; d = M.aa[1][0]; // d = 25 > >
Связанные темы
Инициализация массива статических объектов в Java
В C++ общеизвестной и полезной практикой является использование списка инициализации для задания значений массива. При этом крайне удобно инициализировать при помощи фигурных скобок объекты в которых поля являются открытыми. Это либо структуры(struct) либо классы, у которых все поля открыты(перед ними указан access specifier как public).
Рассмотрим обычную структуру :
struct my_unary_function string name; string detect_name; double (*handler) (double); >;
Объекты можно создавать и инициализировать на лету(конструктор нам не нужен!) :
my_unary_function sin_func = "Синус", "sin", sin>;
Обратите внимание на синтаксис — во-первых, наличие фигурных скобок. Во-вторых — строгий порядок перечисления значений , соответствующий порядку определения переменных в структуре. У нового объекта — name=”Синус”, detec_name=”sin”, handler=”&sin”.
Теперь, собственно массивы, которые удобно инициализировать также как объекты :
my_unary_function math_functions[] = "Синус", "sin", sin>, "Косинус", "cos", cos>, "Тангенс", "tan", tan> >;
Добавив всего-лишь одну строчку расширится функционал программы. Если пишется калькулятор с поддержкой простейших математических вычислений — то все функции можно определять по полю detect_name в этом массиве, а обработчик определяется полем handler.
Java — встроенная инициализация статических массивов из объектов. В Java — немного другая история. Чаще всего используются статические массивы, тип элементов которых объявлен рядом с ними.
Пример такого определения :
public class InnerClassTest static class Employee private String name; private double salary; public Employee(String n, double s) name = n; salary = s; > public void print() System.out.println(name + " " + salary); > > static Employee[] staff = new Employee[] new Employee("Harry Hacker", 3500), new Employee("Carl Cracker", 7500), new Employee("Tony Tester", 3800), >; public static void main(String[] args) for (Employee e: staff) e.print(); > > >
А можно было бы разделить инициализацию и поместить её в специальный static-блок :
public class Main static Integer[] integerArray; static integerArray = new Integer[] new Integer(1), new Integer(2) >; > public static void main(String args[]) for (int i = 0; i integerArray.length; i++) System.out.println(integerArray[i]); > > >
Такой static-блок является функциональным блоком и в нём также можно выполнять любые действия :
static ArrayListString> list = new ArrayListString>(); static list.add("Bart"); list.add("Lisa"); list.add("Marge"); list.add("Barney"); list.add("Homer"); list.add("Maggie"); System.out.print("Hello!"); >
На самом деле для инициализации ArrayList можно использовать метод java.util.Arrays.asList :
public static final ListString> favorites = Arrays.asList("EJB", "JPA", "Glassfish", "NetBeans");