Статический инициализатор в Java



мой вопрос касается одного конкретного использования статического ключевого слова. Можно использовать static ключевое слово для покрытия блок кода внутри класса, который не принадлежит к какой-либо функции. Например, компилируется следующий код:



public class Test {
private static final int a;
static {
a = 5;
doSomething(a);
}
private static int doSomething(int x) {
return (x+5);
}
}


если убрать static ключевое слово он жалуется, потому что переменная a - это final. Однако можно удалить оба final и static ключевые слова и сделать его компиляции.



это сбивает меня с толку в обоих направлениях. Как я предполагается иметь раздел кода, который не принадлежит ни одному методу? Как можно вызвать его? В общем, какова цель этого использования? Или лучше, где я могу найти документацию об этом?

973   9  

9 ответов:

блок кода со статическим модификатором означает класс инициализатор; без модификатора static блоке кода экземпляр инициализатор.

инициализаторы классов выполняются в том порядке, в котором они определены (сверху вниз, как и простые инициализаторы переменных), когда класс загружен (на самом деле, когда он разрешен, но это техническая сторона).

инициализаторы экземпляра выполняются в порядке, определенном при создании класса экземпляр создается непосредственно перед выполнением кода конструктора, сразу после вызова супер конструктора.

если убрать static с int a, оно становится переменной экземпляра, который вы не можете получить доступ из статического блока инициализации. Это не удастся скомпилировать с ошибкой "нестатическая переменная a не может ссылаться из статического контекста".

если вы также удалить static из блока инициализатора он становится экземпляром инициализатор и так int a инициализируется при строительстве.

уфф! что такое статический инициализатор?

статический инициализатор-это static {} блок кода внутри класса java и выполняется только один раз перед вызовом конструктора или метода main.

ОК! Сказать мне больше...

  • - это блок кода static { ... } внутри любого класса java. и выполняется виртуальной машиной при вызове класса.
  • нет return поддерживаются операторы.
  • нет аргументов поддерживаемый.
  • нет this или super поддерживаются.

хм, где я могу его использовать?

может быть использован в любом месте вы чувствуете себя хорошо :) это просто. Но я вижу, что большую часть времени он используется при подключении к базе данных, инициализации API, регистрации и т. д.

Не просто лай! где же пример?

package com.example.learnjava;

import java.util.ArrayList;

public class Fruit {

    static {
        System.out.println("Inside Static Initializer.");

        // fruits array
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Orange");
        fruits.add("Pear");

        // print fruits
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
        System.out.println("End Static Initializer.\n");
    }

    public static void main(String[] args) {
        System.out.println("Inside Main Method.");
    }
}

выход???

Внутри Статического Инициализатора.

Яблоко

оранжевый

груша

Завершить Статический Инициализатор.

Внутри Метода Main.

надеюсь, что это помогает!

The static блок является "статическим инициализатором".

он автоматически вызывается при загрузке класса, и нет другого способа вызвать его (даже через отражение).

Я лично только когда-либо использовал его при написании кода JNI:

class JNIGlue {
    static {
        System.loadLibrary("foo");
    }
}

это непосредственно из http://www.programcreek.com/2011/10/java-class-instance-initializers/

1. Порядок Исполнения

посмотрите на следующий класс, вы знаете, какой из них выполняется первым?

public class Foo {

    //instance variable initializer
    String s = "abc";

    //constructor
    public Foo() {
        System.out.println("constructor called");
    }

    //static initializer
    static {
        System.out.println("static initializer called");
    }

    //instance initializer
    {
        System.out.println("instance initializer called");
    }

    public static void main(String[] args) {
        new Foo();
        new Foo();
    }
}

выход:

статический инициализатор называется

инициализатор экземпляра под названием

конструктор под названием

инициализатор экземпляра под названием

конструктор под названием

2. Как работает инициализатор экземпляра Java?

инициализатор экземпляра выше содержит инструкцию println. Чтобы понять, как это работает, мы можем рассматривать его как оператор присваивания переменной, например,b = 0. Это может сделать его более очевидным для понимания.

вместо

int b = 0, вы могли бы написать

int b;
b = 0;

таким образом, инициализаторы экземпляра и инициализаторы переменных экземпляра в значительной степени тот же.

3. Когда инициализаторы экземпляра полезны?

инициализаторы экземпляров используются редко, но все же это может быть полезной альтернативой инициализаторам переменных экземпляра, если:

  1. код инициализатора должен обрабатывать исключения
  2. выполнить вычисления, которые не могут быть выражены с помощью инициализатора переменной экземпляра.

конечно, такой код может быть написан в конструкторах. Но если класс имел несколько конструкторы, вам придется повторить код в каждом конструкторе.

С инициализатором экземпляра вы можете просто написать код один раз, и он будет выполняться независимо от того, какой конструктор используется для создания объекта. (Я думаю, это просто концепция, и она не часто используется.)

другой случай, в котором инициализаторы экземпляра полезны, - это анонимные внутренние классы, которые вообще не могут объявлять никаких конструкторов. (Будет ли это хорошее место для размещения журнала функции?)

спасибо Derhein.

Также обратите внимание, что анонимные классы, реализующие интерфейсы [1], не имеют конструкторов. Поэтому инициализаторы экземпляра необходимы для выполнения любых видов выражений во время строительства.

"final" гарантирует, что переменная должна быть инициализирована до окончания кода инициализатора объекта. Аналогично "статический финал" гарантирует, что переменная будет инициализирована к концу кода инициализации класса. Пропуск "статического" из вашего кода инициализации превращает его в код инициализации объекта; таким образом, ваша переменная больше не удовлетворяет его гарантиям.

вы не будете писать код в статический блок, который должен быть вызван в любом месте программы. Если цель кода должна быть вызвана, то вы должны поместить его в метод.

вы можете написать статические блоки инициализатора для инициализации статических переменных при загрузке класса, но этот код может быть более сложным..

статический блок инициализации выглядит способ без имени, без аргументов и без возвращаемого типа. Поскольку вы никогда не называете его, ему не нужно имя. Он вызывается только тогда, когда виртуальная машина загружает класс.

когда разработчик использует блок инициализатора, компилятор Java копирует инициализатор в каждый конструктор текущего класса.

пример:

следующий код:

class MyClass {

    private int myField = 3;
    {
        myField = myField + 2;
        //myField is worth 5 for all instance
    }

    public MyClass() {
        myField = myField * 4;
        //myField is worth 20 for all instance initialized with this construtor
    }

    public MyClass(int _myParam) {
        if (_myParam > 0) {
            myField = myField * 4;
            //myField is worth 20 for all instance initialized with this construtor
            //if _myParam is greater than 0
        } else {
            myField = myField + 5;
            //myField is worth 10 for all instance initialized with this construtor
            //if _myParam is lower than 0 or if _myParam is worth 0
        }
    }

    public void setMyField(int _myField) {
        myField = _myField;
    }


    public int getMyField() {
        return myField;
    }
}

public class MainClass{

    public static void main(String[] args) {
        MyClass myFirstInstance_ = new MyClass();
        System.out.println(myFirstInstance_.getMyField());//20
        MyClass mySecondInstance_ = new MyClass(1);
        System.out.println(mySecondInstance_.getMyField());//20
        MyClass myThirdInstance_ = new MyClass(-1);
        System.out.println(myThirdInstance_.getMyField());//10
    }
}

эквивалентно:

class MyClass {

    private int myField = 3;

    public MyClass() {
        myField = myField + 2;
        myField = myField * 4;
        //myField is worth 20 for all instance initialized with this construtor
    }

    public MyClass(int _myParam) {
        myField = myField + 2;
        if (_myParam > 0) {
            myField = myField * 4;
            //myField is worth 20 for all instance initialized with this construtor
            //if _myParam is greater than 0
        } else {
            myField = myField + 5;
            //myField is worth 10 for all instance initialized with this construtor
            //if _myParam is lower than 0 or if _myParam is worth 0
        }
    }

    public void setMyField(int _myField) {
        myField = _myField;
    }


    public int getMyField() {
        return myField;
    }
}

public class MainClass{

    public static void main(String[] args) {
        MyClass myFirstInstance_ = new MyClass();
        System.out.println(myFirstInstance_.getMyField());//20
        MyClass mySecondInstance_ = new MyClass(1);
        System.out.println(mySecondInstance_.getMyField());//20
        MyClass myThirdInstance_ = new MyClass(-1);
        System.out.println(myThirdInstance_.getMyField());//10
    }
}

Я надеюсь, что мой пример понятен разработчикам.

статический блок кода может использоваться для создания экземпляра или инициализации переменных класса (в отличие от переменных объекта). Таким образом, объявление "a" static означает, что только один общий для всех тестовых объектов, а статический блок кода инициализирует "a" только один раз, когда тестовый класс сначала загружается, независимо от того, сколько тестовых объектов создано.

статическое ключевое слово может использоваться с классом, переменной, методом и блоком. Статические члены принадлежат классу, а не конкретному экземпляру, это означает, что если вы делаете член статическим, вы можете получить к нему доступ без объекта. Пример :

здесь у нас есть статический метод myStatic(), мы можем вызвать этот метод без какого-либо объекта, потому что когда мы делаем член статическим, он становится уровнем класса. Если мы удалим ключевое слово static и сделаем его нестатическим, то нам нужно будет создать объект класса in для того, чтобы назвать его

статические члены являются общими для всех экземпляров(объектов) класса, а нестатические члены отдельно для каждого экземпляра класса.

class SimpleStaticExample {
//static method
static void myStatic()
{
    System.out.println("my Static Method");
}

public static void main(String[] args)
{
      /* You can see that we are calling this
       * method without creating any object. 
       */
       myStatic();
 }
}

вывод : мой статический метод

Comments

    Ничего не найдено.