Подтвердить что ты не робот

В каком порядке выполняются статические блоки и блоки инициализации при использовании наследования?

У меня есть два класса Parent и Child

public class Parent {    
    public Parent() {
        System.out.println("Parent Constructor");
    }    
    static {
        System.out.println("Parent static block");    
    }    
    {
        System.out.println("Parent initialisation  block");
    }
}

public class Child extends Parent {    
    {
        System.out.println("Child initialisation block");
    }
    static {
        System.out.println("Child static block");
    }

    public Child() {
        System.out.println("Child Constructor");
    }    
    public static void main(String[] args) {
        new Child();    
    }
}

Выходной код вышеуказанного кода будет

Parent static block
Child static block
Parent initialization  block
Parent Constructor
Child initialization block
Child Constructor

Почему Java выполняет код в этом порядке? Каковы правила, определяющие порядок выполнения?

4b9b3361

Ответ 1

В игре есть несколько правил

  • статические блоки всегда запускаются до создания объекта, поэтому вы видите сообщения печати от обоих родителей и дочерних статических блоков
  • Теперь, когда вы вызываете конструктор подкласса (дочернего), этот конструктор неявно вызывает super(); перед выполнением его собственного конструктора. Блок инициализации вступает в игру еще до вызова конструктора, поэтому его сначала вызывают. Итак, теперь ваш родитель создан, и программа может продолжить создание дочернего класса, который будет проходить тот же процесс.

Пояснения:

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

Ответ 2

Я учусь визуально, поэтому здесь визуальное представление порядка, как SSCCE:

public class Example {

  static {
    step(1);
  }

  public static int step_2 = step(2);
  public int step_6 = step(6);

  public Example() {
    step(8);
  }

  {
    step(7);
  }

  // Just for demonstration purposes:
  public static int step(int step) {
    System.out.println("Step " + step);
    return step;
  }
}

public class ExampleSubclass extends Example {

  {
    step(9);
  }

  public static int step_3 = step(3);
  public int step_10 = step(10);

  static {
    step(4);
  }

  public ExampleSubclass() {
    step(11);
  }

  public static void main(String[] args) {
    step(5);
    new ExampleSubclass();
    step(12);
  }
}

Это печатает:

Step 1
Step 2
Step 3
Step 4
Step 5
Step 6
Step 7
Step 8
Step 9
Step 10
Step 11
Step 12

Имейте в виду, что порядок частей static имеет значение; оглянемся на разницу между порядком вещей Example static и ExampleSubclass.

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

Ответ 3

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

второе - перейти на Статический блок против блока инициализатора в Java? & прочитайте принятый ответ там.

Изменить:

  1. Выполнение происходит способом SIC - Статический (не статичный) Initializer & Конструктор.
  2. (Не статично) Инициализатор копируется в каждый конструктор - В ТОПе! (поэтому строки 3/4/5/6)
  3. Перед инициализацией класса его прямой суперкласс должен быть инициализирован - http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4 (следовательно, родительский статический блок появляется первым).

Ответ 4

  • Статические блоки инициализации выполняются во время загрузки класса.
  • В иерархии классов порядок выполнения статических блоков инициализации будет начинаться с класса верхнего уровня.
  • В классе порядок выполнения статического блока сверху вниз.
  • Вышеупомянутое правило применяется независимо от того, где статический блок присутствует в классе.

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

  • Блоки инициализации экземпляра будут выполнены после вызова super(); в конструкторе.
    • Всегда супер(); это самый первый оператор в конструкторе по умолчанию.

В вашем коде при создании дочернего объекта:

  • Конструктор по умолчанию класса Child исполняется.
  • Это вызовет супер(); конструктор.
  • Затем выполняется конструктор суперкласса.
  • Родительский класс выполнит свой super(); вызов.
  • После этого исполняются блоки экземпляра init в классе Parent (сверху вниз).
  • Затем выполняется код внутри конструктора (если есть).
  • Затем он вернется в класс Child и выполнит блоки инициализации экземпляра класса Child.
  • Наконец код в дочернем конструкторе выполняется (если существует).

Ответ 5

Статический блок в java выполняется перед основным методом. Если объявить статический блок в классе java, он выполняется, когда класс загружается. Это инициализируется статическими переменными. Он в основном используется в JDBC. Статический блок в java выполняется каждый раз, когда класс загружается. Это также известно как статический блок инициализации. Статический блок в java инициализирует загрузку класса в память, это означает, что JVM читает байтовый код. Инициализация может быть любой; это может быть переменная инициализация или что-либо еще, что должно быть разделено всеми объектами этого класса. Статический блок - это нормальный блок кода, заключенный в фигурные скобки {}, которому предшествует статическое ключевое слово.

поэтому сначала выполняется статический блок.

Блоки инициализации экземпляра: выполняется каждый раз, когда создается экземпляр класса.

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

тогда конструктор выполнил

Ответ 6

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

Ответ 7

Просто хотел поделиться своими выводами. Я прочитал в одном из ответов на другой поток, что статические блоки выполняются сначала перед статическими полями, что неверно. Это зависит от того, что на первом месте, статического поля или статического блока. Посмотрите ниже код. Он попытается перевести что-то в перспективе.

  • JVM ищет класс, который имеет public static void main (String args []), чтобы он мог загрузить этот класс.
  • Затем он инициализирует статические поля этого класса (если они попадают перед статическими блоками). Эти поля могут вызывать статические методы этого класса. Если они вызовут статический метод этого класса, то этот метод будет обслуживаться. Если они вызывают статический метод другого класса, тогда статические поля или блоки этого класса (в зависимости от того, что на первом месте) сначала инициализируются, тогда этот вызов метода обслуживается.
  • Затем он перемещается в статические блоки.
  • Возврат к основному методу.

    class TestLab {
    static int method(String a) {
        System.out.println("in static method of TestLab" + " Coming from " + a);
        System.out.println("b is " + b);
        return 6;
    }
    
    static int a = method("Line 11");
    static int b = 7;
    
    TestLab() {
        System.out.println("Inside test lab constructor");
    }
    
    static {
        System.out.println("In static block of TestLab");
    }
    
    }
    
    public class Test1 {
    public static void main(String[] args) {
        System.out.println("inside main method of Test 1");
        int a = TestLab.method("Line 26");
    }
    
    // static Test ref=new Test();
    Test1() {
        System.out.println("Default Constructor of Test1");
    }
    
    {
        System.out.println("In instance block of Test1");
    }
    static int d = TestLab.method("Line 37");
    static int e = methodOfTest1();
    static {
        System.out.println("In Static Block of Test1");
    }
    
    static int methodOfTest1() {
        System.out.println("inside static method:mehtodOfTest1()");
        return 3;
    }
    }
    

Вот результат:

in static method of TestLab Coming from Line 11
b is 0
In static block of TestLab
in static method of TestLab Coming from Line 37
b is 7
inside static method:mehtodOfTest1()
In Static Block of Test1
inside main method of Test 1
in static method of TestLab Coming from Line 26
b is 7

Ответ 8

Вот что я нашел при подготовке к сертификации.

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

Затем он выполнит инициализацию init/инициализацию переменной экземпляра. Если там есть несколько инициализаций/инициализация переменных, она выполнит ее в том порядке, в котором она появится,

Затем он заглянет в конструктор.

Ответ 9

поток управления -

статический блок → блок инициализации → и, наконец, конструктор.

static block → Этот статический блок будет выполняться только один раз, когда элемент управления попадает в класс. (JVM Load this class)

Блок инициализации → Этот блок инициализации будет выполняться всякий раз, когда новый объект, созданный для класса (он будет выполнен из второго оператора конструктора, а затем после операторов конструктора - помните, что первая инструкция конструктора будет супер()/это())

Конструктор → Это будет получать всякий раз, когда создается новый объект.

Ответ 10

Статический блок запускается, когда класс загружается в JVM. Хотя блок init копируется в конструктор, объект которого будет создан и запускается до создания объекта.

Ответ 11

1.Статический блок init выполняется во время загрузки класса только один. Блок 2.Init выполняется каждый раз перед созданием объекта класса.

ссылка :- https://www.youtube.com/watch?v=6qG3JE0FbgA&t=2s