static {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
A = Integer.parseInt(reader.readLine());
B = Integer.parseInt(reader.readLine());
}
catch (IOException e) {
e.printStackTrace();
}
}
Константин
51 уровень
Почему вне static - блока работать не будет?
Решен
Комментарии (14)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
hidden #598481
8 декабря 2022, 16:30полезный
Вне статик блока - это где? Ты же не можешь просто в классе код писать, можно либо в методе, либо в блоке кода.
Или ты имеешь в виду сделать блок кода нестатическим, то это потому что нестатический блок кода будет выполнен при создании объекта, а статические раньше, при загрузке класса.
Можно сделать так:Это позволит выполнить код по вводу чисел, но значение MIN все равно будет вычислено ДО того, как наступит выполнение метода main, т.е. до ввода чисел с консоли, поэтому работать не будет :)
+2
Константин
9 декабря 2022, 12:41
Поспал и сейчас начинаю что-то понимать)
Как я понял, со статик-блоком вызывается несуществующий статический конструктор и переменные A и B инициализируются сразу считанными значениями. То есть не сперва нулями, а потом считываемыми, а сразу считываемыми, неявно выполняется код
public class Solution extends Object {
public static int A;
public static int B;
public static Solution() {
super();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
A = Integer.parseInt(reader.readLine());
B = Integer.parseInt(reader.readLine());
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Если оно происходит вне статика, то неявно происходит инициацлизация нулями.
public class Solution extends Object{
public static int A;
public static int B;
public static Solution() {
super();
A = 0;
B = 0;
}
}
И тогда все действия производятся с нулями и в итоге выводится 0. Так?
0
Константин
9 декабря 2022, 12:54
То, что можно код писать просто в блоке кода вне метода даже не знал, сейчас по твоим комментам сильно расширю понимание джавы, но ответ породил больше вопросов, чем ответов)
1) Как я понял, статические переменные и переменные класса инициализируются раньше выполнения статических методов, если для инициализации переменных методы не нужны? А если для переменной MIN нужен метод min, то метод min, соответственно, выполняется раньше?
2) А) почему без new Solution(); выводится 0 и считывание вообще не происходит? Почему не происходит инициализации переменных нулями, а потом выполнение нестатического блока кода, где считывается и присваиваются переменным считываемые значения?
Б) Почему с new Solution(); происходит считывание и выводится 0?
0
Константин
9 декабря 2022, 13:04
Хотя опять же, если переменные класса инициализируются раньше методов, то почему не работает вызов полей без создания объекта в следующей задаче?
Получается иерархия статические переменные - статические методы - переменные класса?
Или переменные объекта в принципе инициализируются только во время/после его создания, а без создания они никогда не будут проинициализированы?
Получается иерархия статические переменные - статические методы - переменные класса?
Или переменные объекта в принципе инициализируются только во время/после его создания, а без создания они никогда не будут проинициализированы? 0
hidden #598481
9 декабря 2022, 14:50полезный
> Как я понял, со статик-блоком вызывается несуществующий статический конструктор и переменные A и B инициализируются сразу считанными значениями. То есть не сперва нулями, а потом считываемыми, а сразу считываемыми, неявно выполняется код
Никакого несуществующего статического конструктора не существует, он же несуществующий :))
Сейчас постараюсь объяснить подробнее и по порядку.
Поля, т.е. переменные класса (и статические и нестатические) инициализируются всегда при создании. То есть в момент, когда поле создается, сразу инициализируется значением. Это будет значение null для ссылочных типов данных, 0 для примитивов (false для boolean). Если создание переменной совмещено в одной строке с инициализацией, то будет присвоено соответственно значение, полученное из правой части выражения, после знака "=". Например:
+1
hidden #598481
9 декабря 2022, 14:50полезный
В примере, который ты привёл в вопросе, со статик блоком, присвоение нового значения выполняется не одновременно с созданием, а сразу после, следующим действием. То есть если между созданием и присвоением нового значения других действий нет, то и разницы нет по большому счёту. Но мы можем проверить это
+1
hidden #598481
9 декабря 2022, 14:51полезный
> Как я понял, статические переменные и переменные класса инициализируются раньше выполнения статических методов, если для инициализации переменных методы не нужны? А если для переменной MIN нужен метод min, то метод min, соответственно, выполняется раньше?
Давай не будем сюда примешивать нестатические переменные. Они вообще не существуют в статическом контексте и создаются только при создании объекта (при этом каждый раз, при создании каждого объекта). То же самое касается и нестатических блоков кода. По сути нестатический блок кода - это действие, которое каждый раз выполняется перед выполнением конструктора объекта. Это было лирическое отступление про нестатические поля и блоки. Они не существуют (поля) и не выполняются (блоки), пока не создаются объекты класса.
Вернёмся к статикам. Статические переменные и блоки кода выполняются один раз при первом обращении к самому классу. Если ты запускаешь метод main в этом самом классе, то исполнение программы начинается с создания самого класса, всех его статических полей и исполнения статических блоков кода. Методы вообще не могут исполняться "просто так", они исполняются ровно тогда, когда происходит вызов этого метода: в статическом блоке, при инициализации переменной или в другом методе. А весь статический контекст создается путем выполнения статических команд последовательно сверху вниз, т.е. порядок играет роль.
+2
hidden #598481
9 декабря 2022, 14:51полезный
Например, посмотри на вывод этого кода:
Второй блок выполняется только после того, как выполнятся методы A и В. При этом, если из первого статического попытаться обратиться к переменной Х, то компилятор не даст запустить этот код, так как будет невозможная ссылка на ещё не созданную переменную, а из метода к ней обратиться можно, т.к. в этом случае переменная создастся автоматически при первом к ней обращении. То есть до выполнения doB() переменной X вообще не существует, а при попадании в doB() она создается еще до вывода строки "doing B...". Можешь посмотреть сам в дебаггере.
Теперь можем вернуться к тому примеру, который я привёл в своём первом комменте.
> почему без new Solution(); выводится 0 и считывание вообще не происходит? Почему не происходит инициализации переменных нулями, а потом выполнение нестатического блока кода, где считывается и присваиваются переменным считываемые значения?
Как я тебе уже сказал, нестатические поля и блоки выполняются только при создании объекта. При этом, поскольку статический контекст к тому времени существует, то из нестатического контекста обращаться к статическому можно, а наоборот нет.
Поэтому если объект не создать, то нестатический блок кода вызван не будет. А если создать пять объектов, то он будет вызван 5 раз. Только не забудь убрать System.in из ресурсов, а то произойдет попытка чтения из закрытого потока, поймаешь исключение.
+1
hidden #598481
9 декабря 2022, 14:52полезный
> Почему с new Solution(); происходит считывание и выводится 0?
Потому что сначала выполняется создание класса, сопряженное с созданием всего статического контекста: создадутся все три поля, выполнится поиск значение MIN между двумя нулями и только после этого начнётся выполнение main: создастся объект Solution, а в процессе создания выполнится нестатический блок кода и произойдёт ввод новых значений A и В.
> Хотя опять же, если переменные класса инициализируются раньше методов, то почему не работает вызов полей без создания объекта в следующей задаче?
Элементарно потому, что это поля объекта. И выводить значения ты должен для конкретного объекта: у одного солюшена они одни, у другого другие.
> Получается иерархия статические переменные - статические методы - переменные класса?
Это не иерархия, а последовательность создания: по порядку сверху вниз. Статическое - при первом обращении к классу, а нестатическое при каждом создании объекта
> Или переменные объекта в принципе инициализируются только во время/после его создания, а без создания они никогда не будут проинициализированы?
Да. Не только инициализируются, они и создаются тогда же.
+1
Константин
9 декабря 2022, 16:05
1) Во-первых, ЖЭСТАЙЧАЙШЭ благодарю за разъяснения, 40 минут это всё читал и в итоге догнал)
2) "То есть до выполнения doB() переменной X вообще не существует, а при попадании в doB() она создается еще до вывода строки "doing B..."." То, что создаётся между обращением к doB и выводом, было совсем не очевидно)
3) глянул, что new Solution(); 2 раза уже вызывает ошибку обращения к закрытому потоку. А почему так? Почему не создаётся новый поток для каждого создаваемого объекта, если нестатические блоки кода, как и локальные переменные не существуют/не исполняются до создания объекта?
4) В каких случаях ещё не стоит оборачивать что бы то ни было в try-with-resourses? А то во время чтения лекции с примерами возникло стойкое ощущение, что оборачивать нужно всё подряд и оно классно)
5) я, может, чего-то не догоняю, но, насколько помню, не только статические заполняются по умолчанию, но и нестатические перменные класса тоже инициализируются по умолчанию. То есть что в первом случае, что во втором, они должны быть нулями по умолчанию.
Пока писал, догнал вроде) Когда статик, оно сразу 0, когда не статик, 0 только при создании объекта. Но я почему-то был уверен, что нестатические переменные класса доступны в классе и с ними можно было работать как с проинициализированными по умолчанию. Сейчас буду искать корни этого заблуждения)
Пока писал, догнал вроде) Когда статик, оно сразу 0, когда не статик, 0 только при создании объекта. Но я почему-то был уверен, что нестатические переменные класса доступны в классе и с ними можно было работать как с проинициализированными по умолчанию. Сейчас буду искать корни этого заблуждения)
0
Константин
9 декабря 2022, 16:08
6) если происходит загрузка класса, в котором есть внутренние / вложенные классы со статическими блоками, то загрузка статических блоков внутреннего класса тоже происходит сразу или пока к нему не обратились, его как будто и нет? Вот в данном случае хронология загрузки класса Cat
0
hidden #598481
9 декабря 2022, 16:31полезный
1. 👌
2. Да, для меня это тоже было в некотором роде сюрпризом.
3. Потому что ты закрываешь не только созданный ридер, а еще и стрим, сам System.in: JVM не может больше получить доступ к системному потоку, пока ты заново не перезапустишь всё. Все эти ридеры и стримы - это обёртки друг над другом, и там везде при вызове close по цепочке вызывается close у объекта, который обернут в текущий объект.
4. Пожалуй, стоит оборачивать всё, кроме системных потоков чтения-записи. Простое правило: открыл? закрой. не открывал? не закрывай :) В некоторых задачах отдельным требованием написано, что систем-ин должен быть закрыт, и в этом случае стоит закрывать, но на практике нет. Шляпное требование какое-то.
5. Правильно догнал в конце, повторяться не буду.
6. Проверь сам. Вынеси мейн из солюшена в третий класс рядом с Solution и в этом мейне создай новый объект Solution. Увидишь, выполнился ли статик кота или нет.
+3
Константин
9 декабря 2022, 16:59
По-пятому нашёл корень) на таких лекционных примерах создалось впечатление, что нестатическими переменными класса можно работать в рамках класса откуда угодно, но никто не сказал, что до создания объекта переменных не существует)
А в шестом не знаю, если имел в виду так, то вроде работает)
То есть по идее загружается и внешний, и внутренний, хотя уже слабо соображаю, нужен отдых)
А в шестом не знаю, если имел в виду так, то вроде работает)
То есть по идее загружается и внешний, и внутренний, хотя уже слабо соображаю, нужен отдых) 0
Денис Enterprise Java Developer
8 декабря 2022, 16:28
Потому, что вне блока статик такая структура работать будет тоже. Ну если ты ее конечно поместишь в какой ни будь метод. А твой вопрос скорее всего относится к другой части кода которую ты сюда выложить не догадался. Равно как и условие задачи.
0