Добавление моих двух центов здесь - всегда по возможности используйте implements Runnable
. Ниже приведены два оговорки о том, почему вы не должны использовать extends Thread
s
Thread
должен быть сделан final
. По крайней мере, такие методы, как thread.getId()
. См. это обсуждение для ошибки, связанной с расширением Thread
s. См. http://pastebin.com/BjKNNs2G .
public class WaitPuzzle {
public static void main(String[] args) throws InterruptedException {
DoNothing doNothing = new DoNothing();
new WaitForever(doNothing).start();
new WaitForever(doNothing).start();
new WaitForever(doNothing).start();
Thread.sleep(100);
doNothing.start();
while(true) {
Thread.sleep(10);
}
}
static class WaitForever extends Thread {
private DoNothing doNothing;
public WaitForever(DoNothing doNothing) {
this.doNothing = doNothing;
}
@Override
public void run() {
synchronized (doNothing) {
try {
doNothing.wait(); // will wait forever here as nobody notifies here
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Unreachable Code");
}
}
}
static class DoNothing extends Thread {
@Override
public void run() {
System.out.println("Do Nothing ");
}
}
}
Я изучаю визуально, так что вот визуальное представление порядка, как SSCCE:
public class Example {
static {
step(1);
}
public static int step_1 = 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
's static
и ExampleSubclass
.
Также обратите внимание, что блок инициализации экземпляра всегда выполняется перед конструктором независимо от порядка , Однако порядок имеет значение между блоком инициализации и инициализатором поля.
Загрузите только первый класс (комментируйте предложение extend), чтобы увидеть простой поток.
second - перейти к Блок статического блока против блока инициализации в Java? & amp; прочитайте принятый ответ там.
Редактирование:
(В вашем коде сначала будут выполняться родительские статические блоки, а затем статические блоки дочернего класса.)
В вашем коде при создании объекта Child:
Было бы очень полезно выполнить процесс построения объекта с помощью пошагового отладчика, имея представление, в котором вы можете видеть, как ваш объект проходит через фазы. Я нашел это очень полезным для очистки перспективы с более высокой точки зрения. Eclipse может помочь вам в этом с его шагом отладчика в функцию.
В игре существует несколько правил
super();
перед выполнением собственного конструктора. Блок инициализации вступает в игру еще до вызова конструктора, поэтому его сначала называют. Итак, теперь ваш родитель создан, и программа может продолжить создание дочернего класса, который будет проходить тот же процесс. Пояснения:
blockquote>
- Статический блок родителя выполняется первым, потому что он загружается первым, а статические блоки вызывается при загрузке класса.
Просто хотел поделиться своими выводами. Я прочитал в одном из ответов на другой поток, что статические блоки выполняются сначала перед статическими полями, что неверно. Это зависит от того, что на первом месте, статического поля или статического блока. Посмотрите ниже код.
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
поток управления -
статический блок -> блок инициализации -> и, наконец, конструктор.
static block -> Этот статический блок будет выполняться только один раз, когда появится управление к классу. (JVM Загрузить этот класс)
Блок инициализации -> Этот блок инициализации будет выполняться всякий раз, когда новый объект создан для класса (он будет выполнен из второго оператора конструктора затем следующие инструкции конструктора - помните, что первая инструкция конструктора будет супер () / this ())
Constructor -> Это будет получаться всякий раз, когда создается новый объект.
Вот что я нашел во время подготовки к сертификации.
Пока мы запускаем класс, происходит первая статическая блоки / статическая переменная. Если есть несколько статических блоков, он выполнит его в том порядке, в котором он появится,
Затем он выполнит инициализацию блоков / инициализацию переменной экземпляра. Если существует несколько инициализаций инициализации / инициализации переменных, она будет выполняться он в том порядке, в котором он появляется,
. Затем он будет смотреть на конструктор.
Статический блок в java выполняется перед основным методом. Если объявить статический блок в классе java, он выполняется, когда класс загружается. Это инициализируется статическими переменными. Он в основном используется в JDBC. Статический блок в java выполняется каждый раз, когда класс загружается. Это также известно как статический блок инициализации. Статический блок в java инициализирует загрузку класса в память, это означает, что JVM читает байтовый код. Инициализация может быть любой; это может быть переменная инициализация или что-либо еще, что должно быть разделено всеми объектами этого класса. Статический блок - это нормальный блок кода, заключенный в фигурные скобки {}, которому предшествует статическое ключевое слово.
, поэтому статический блок выполняется первым.
Блоки инициализации экземпляра: выполняется каждый раз, когда экземпляр класса.
, поэтому следующий блок инициализации, выполняемый при создании экземпляра класса.
, затем выполнен конструктор
Статический блок запускается, когда класс загружается в JVM. Хотя блок init копируется в конструктор, объект которого будет создан и запускается до создания объекта.
2, 1, 4, 3, 5, 6, 7, 8, 9, 10
. Замечу, что в своем ответе – Ben Leggiero 18 December 2017 в 00:51