В чем разница между инициализацией внутри static
блока:
public class staticTest {
static String s;
static int n;
static double d;
static {
s = "I'm static";
n = 500;
d = 4000.0001;
}
...
И индивидуальная статическая инициализация:
public class staticTest {
static String s = "I'm static";
static int n = 500;
static double d = 4000.0001;
....
java
static-initialization
Адам Матан
источник
источник
Ответы:
Блоки статической инициализации допускают более сложную инициализацию, например, с использованием условных выражений:
static double a; static { if (SomeCondition) { a = 0; } else { a = 1; } }
Или когда требуется больше, чем просто построение: при использовании построителя для создания вашего экземпляра необходима обработка исключений или работа, отличная от создания статических полей.
Блок статической инициализации также запускается после встроенных статических инициализаторов, поэтому допустимо следующее:
static double a; static double b = 1; static { a = b * 4; // Evaluates to 4 }
источник
Типичное использование:
private final static Set<String> SET = new HashSet<String>(); static { SET.add("value1"); SET.add("value2"); SET.add("value3"); }
Как бы вы это сделали без статического инициализатора?
источник
SET
и используйте инициализатор переменной (private final static Set<String> SET = createValueSet()
). Что, если у вас есть 5 наборов и 2 карты, вы бы просто свалили их все в одинstatic
блок?Вы можете использовать блок try / catch внутри,
static{}
как показано ниже:MyCode{ static Scanner input = new Scanner(System.in); static boolean flag = true; static int B = input.nextInt(); static int H = input.nextInt(); static{ try{ if(B <= 0 || H <= 0){ flag = false; throw new Exception("Breadth and height must be positive"); } }catch(Exception e){ System.out.println(e); } } }
PS: Ссылаются отсюда !
источник
Другая причина - обработка исключений во время инициализации. Например:
static URL url; static { try { url = new URL("https://blahblah.com"); } catch (MalformedURLException mue) { //log exception or handle otherwise } }
Это полезно для конструкторов, которые раздражающе выбрасывают проверенные исключения, как указано выше, или для более сложной логики инициализации, которая может быть подвержена исключениям.
источник
Иногда вы хотите сделать больше, чем просто присвоить значения статическим переменным. Поскольку вы не можете помещать произвольные операторы в тело класса, вы можете использовать блок статического инициализатора.
источник
В вашем примере разницы нет; но часто начальное значение сложнее, чем удобно выразить в одном выражении (например, это a
List<String>
, содержимое которого лучше всего выражаетсяfor
-loop; или это a,Method
которое может не существовать, поэтому требуются обработчики исключений), и / или статические поля должны быть установлены в определенном порядке.источник
static
block может использоваться для инициализации экземпляра singleton , чтобы предотвратить использование синхронизированногоgetInstance()
метода.источник
Технически без него можно обойтись. Некоторые предпочитают использовать многострочный код инициализации вместо статического метода. Я вполне доволен использованием статического инициализатора для относительно простой инициализации нескольких состояний.
Конечно, я почти всегда делал свою статику
final
и указывал на неизменяемый объект.источник
Статическое ключевое слово (будь то переменная или блок) принадлежит классу. Поэтому, когда класс вызывается, эти переменные или блоки выполняются. Таким образом, большая часть инициализации будет выполнена с помощью ключевого слова static. Поскольку он принадлежит самому классу, класс может напрямую обращаться к нему, не создавая экземпляра класса.
Пример:
class Shoe { int size; String colour; static String brand = "Nike"; public Shoe(int size, String colour) { super(); this.size = size; this.colour = colour; } void displayShoe() { System.out.printf("%-2d %-8s %s %n",size,colour, brand); } public static void main(String args[]) { Shoe s1 = new Shoe(7, "Blue"); Shoe s2 = new Shoe(8, "White"); System.out.println("================="); s1.displayShoe(); s2.displayShoe(); System.out.println("================="); } }
источник
Блок статического кода позволяет инициализировать поля с помощью не только инструкции, инициализировать поля в другом порядке объявлений, а также может использоваться для условной инициализации.
В частности,
static final String ab = a+b; static final String a = "Hello,"; static final String b = ", world";
не будет работать, потому что a и b объявлены после ab.
Однако я мог использовать статический init. блок, чтобы преодолеть это.
static final String ab; static final String a; static final String b; static { b = ", world"; a = "Hello"; ab = a + b; } static final String ab; static final String a; static final String b; static { b = (...) ? ", world" : ", universe"; a = "Hello"; ab = a + b; }
источник
ab
декларацию под декларациюb
.Мы используем конструкторы для инициализации переменных нашего экземпляра (нестатические переменные, переменные, принадлежащие объектам, а не классу).
Если вы хотите инициализировать переменные класса (статические переменные) и хотите сделать это без создания объекта (конструкторы могут вызываться только при создании объекта), тогда вам нужны статические блоки.
static Scanner input = new Scanner(System.in); static int widht; static int height; static { widht = input.nextInt(); input.nextLine(); height = input.nextInt(); input.close(); if ((widht < 0) || (height < 0)) { System.out.println("java.lang.Exception: Width and height must be positive"); } else { System.out.println("widht * height = " + widht * height); } }
источник
System.out.println("B * H");
это довольно бесполезно. Да и сам ответ довольно расплывчатый. OP не упомянул конструкторы или переменные экземпляра.Блок статической инициализации полезен, если вы хотите инициализировать указанные статические типы класса до первого использования класса. Последующее использование не вызовет никаких статических блоков инициализации. Это прямая противоположность инициализаторам экземпляра, которые инициализируют члены экземпляра.
источник
Если вы хотите оценить какое-либо определенное выражение во время загрузки класса, вы можете использовать статический блок, но помните:
источник