Будет ли статический блок выполняться без основного метода?

Возник вопрос на форуме,

Статический блок даже выполняется без основного метода в прикладной программе.
1. Верно
2. Ложь

Я ответил на вопрос как 2. False и попробовал приведенный ниже код на моей машине. И он ничего не выполнил и не показал никаких ошибок.

public class StaticBlockDemo {
    static {
        System.out.println("Hello World");
    }
}

Так какой правильный ответ? Кстати, я использую Java 7.

Ответы

Ответ 1

Если вы поместите System.exit(0) в конец static -block, он будет работать без ошибок в Java 6 и ниже (без действительного main!). Это происходит из-за того, что блок static выполняется до того, как выполняется поиск корректного метода main, поэтому, если вы выходите из программы в конце статического блока, вы не получите никаких ошибок.

Однако это поведение было изменено в Java 7; теперь вы должны включить явный main, даже если он никогда не будет достигнут.

В Java 7 ответ на вопрос false, но в Java 6 и ниже ответ действительно true.


public class Test {
    static {
        System.out.println("Hello World");
        System.exit(0);
    }
}

Java 6:

Hello World

Java 7:

Error: Main method not found in class Test, please define the main method as:
   public static void main(String[] args)

Ответ 2

Статические блоки выполняются при инициализации класса. Обычно класс main вызывает инициализацию класса начальной загрузки, но есть и другие способы загрузки программы, например, через встроенный API VM .

Вызов метода static main класса вызывает его инициализацию, но так много других вещей:

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

Подробнее см. JLS глава 12.4

Ниже показано это в действии

public class Foo {
  static { System.out.println("Foo initialized"); }

  public static void main(String... argv) {
    Initialized.callingThisCausesClassInitialization();
  }

  static class Initialized {
    static { System.out.println("Initialized initialized"); }
    static void callingThisCausesClassInitialization() {}
  }

  static class NotInitialized {
    static { System.out.println("NotInitialized initialized"); }
    static void callingThisCausesClassInitialization() {}
  }
}

Запуск foo будет печатать

Foo initialized
Initialized initialized

Он не будет печатать

NotInitialized initialized

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

Похоже, ваш класс имеет такое поведение, потому что он никогда не используется, например NotInitialized.

Ответ 3

Самый проголосовавший ответ "в основном" правильный, но не полностью. Рассмотрим следующий ниже код, где класс имеет основной метод и статический метод. Статический метод WILL выполняет (успешно) ПЕРЕД основным методом и конструктором и создает последовательность: A B C D - это не так, как вы могли подумать.

public class Sequence {
    Sequence() {
        System.out.print("c ");
    }
    {
        System.out.print("B ");
    }
    public static void main(String[] args) {
        new Sequence().go();
    }
    void go() {
        System.out.print("D ");
    }
    static{
        System.out.print("A ");
    }
}

Ответ 4

В java 8 вы не можете запускать программу без явного написания основного метода. Из этого угла ответ ложный. Статический блок не выполняется без основного метода. Ниже приведен фрагмент кода, который показывает порядок инициализации. (Статический блок == > main == > блок инициализации == > конструктор)

public class StaticBlock {

static{
    System.out.println("in static block");
}


{
    System.out.println("in initialization block");
}

public StaticBlock(){
    System.out.println("in const");
}

public static void main(String[] args) {
        System.out.println("in main method");
        StaticBlock block=new StaticBlock();
}

в статическом блоке
в основном методе в блоке инициализации
в const

Ответ 5

abstract class test extends javafx.application.Application {
    static {
        System.out.println("hello");
        System.exit(0);
    }
}

Компиляция с использованием: javac -source 1.6 test.java

Запустить используя: java test

Это будет работать даже с JDK 1.8. 🙂

Ответ 6

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

его экземпляры называются экземплярами классаLoader, которые загружают классы теперь, переходя к деталям этого, следует иерархия с BootStrap ClassLoader, находящаяся в верхней части

Обратите внимание, что загрузчик класса BootStrap сам по себе является экземпляром класса ClassLoader.

Более того, эти экземпляры также выполняют проверку, подготовку, разрешение символических ссылок, чтобы упростить ее выполнение, она выполняет динамическое связывание вашей Java-программы.

теперь, когда ваш компилятор компилирует файл .java, он вставляет открытое статическое конечное поле типа Class вы можете получить доступ к нему в своем java.lang.Class obj = name_of_your_class.class

и он содержит метод getClassLoader, который сообщает экземпляру classLoader, который загружал этот класс.

отлично, только используя эту информацию, ClassLoaders узнают имя загружаемого класса, то есть его полное имя (package.class)

перед тем, как искать файл в своей файловой системе и загрузить его он проверяет со своим родительским экземпляром, что он уже загрузил этот файл, пока эта проверка не распространяется полностью вверху BootclassLoader только если ни один из них не загрузил его, то только этот экземпляр загружает этот файл классов. детали того, как это происходит, в этом контексте не имеют значения.

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

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

из java 7 выполняется поиск основного метода до этого, и если мы не получим эту ошибку во время выполнения но в java 6 и более ранней версии, когда загрузка классов происходила там, статический блок был вынут, а затем он искал, чтобы найти основной метод, но если мы предоставим System.exit(0); в блоке он завершает программу еще до того, как будет выполнен поиск, поэтому у нас не было никакой ошибки

хотя в java 7 зондирование основного метода выполняется до выполнения статического блока, выполнение самого статического блока зависит от успешного нахождения основного метода. Даже если порядок выполнения программы является программой такой же, как в java 6 и более ранней версии.

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

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

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