스태틱 초기화 블록
제가 알기론 "static initialization block"은 한 줄로 할 수 없는 경우 정적 필드의 값을 설정하는 데 사용됩니다.
하지만 나는 왜 우리가 그것을 위해 특별한 블록이 필요한지 이해할 수 없다.예를 들어 필드를 스태틱(값 할당 없음)으로 선언합니다.그런 다음 위에 선언된 정적 필드에 값을 생성하고 할당하는 코드의 여러 줄을 작성합니다.
은 왜 '하다'와 같은 합니까?static {...}
무슨 일입니까?
비정적 블록:
{
// Do Something...
}
클래스의 인스턴스가 생성될 때마다 호출됩니다.스태틱 블록은 클래스 자체가 초기화되었을 때 해당 유형의 오브젝트 수에 관계없이 한 번만 호출됩니다.
예제:
public class Test {
static{
System.out.println("Static");
}
{
System.out.println("Non-static block");
}
public static void main(String[] args) {
Test t = new Test();
Test t2 = new Test();
}
}
다음의 출력이 있습니다.
Static
Non-static block
Non-static block
정적 초기화 블록에 포함되지 않았다면 어디에 있을까요?초기화를 목적으로만 로컬 변수를 선언하고 필드와 구별하려면 어떻게 해야 합니까?예를 들어, 다음과 같이 기술할 수 있습니다.
public class Foo {
private static final int widgets;
static {
int first = Widgets.getFirstCount();
int second = Widgets.getSecondCount();
// Imagine more complex logic here which really used first/second
widgets = first + second;
}
}
iffirst
★★★★★★★★★★★★★★★★★」second
블록에 static
그 앞에 있는 것은 정적 초기화 블록이 아닌 인스턴스 초기화 블록으로 카운트되기 때문에 생성된 인스턴스별로 총 한 번이 아니라 한 번 실행됩니다.
이 경우 대신 스태틱 방식을 사용할 수 있습니다.
public class Foo {
private static final int widgets = getWidgets();
static int getWidgets() {
int first = Widgets.getFirstCount();
int second = Widgets.getSecondCount();
// Imagine more complex logic here which really used first/second
return first + second;
}
}
...하지만 동일한 블록 내에 할당하려는 변수가 여러 개 있거나 할당하지 않은 경우(예를 들어 무언가를 기록하려는 경우 또는 네이티브 라이브러리를 초기화하려는 경우)에는 이 기능이 작동하지 않습니다.
다음은 예를 제시하겠습니다.
private static final HashMap<String, String> MAP = new HashMap<String, String>();
static {
MAP.put("banana", "honey");
MAP.put("peanut butter", "jelly");
MAP.put("rice", "beans");
}
"static" 섹션의 코드는 클래스의 인스턴스가 생성되기 전(및 다른 곳에서 스태틱메서드가 호출되기 전) 클래스 로드 시 실행됩니다.그러면 클래스 리소스를 모두 사용할 수 있습니다.
또한 비정적 이니셜라이저 블록을 사용할 수도 있습니다.이들은 클래스에 대해 정의된 생성자 메서드 집합에 대한 확장과 같이 작동합니다.static 키워드가 생략된 것을 제외하면 스태틱 이니셜라이저 블록과 똑같이 보입니다.
런타임 중에 일부 클래스를 한 번만 로드하는 것과 같이 실제로 값을 할당하지 않을 때도 유용합니다.
예.
static {
try {
Class.forName("com.example.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new ExceptionInInitializerError("Cannot load JDBC driver.", e);
}
}
저기, 또 다른 장점이 있어요. ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★♪해 보세요.getStuff()
서 여 an an an 를 던지다Exception
캐치블록에 속합니다.
private static Object stuff = getStuff(); // Won't compile: unhandled exception.
a then then then thenstatic
여기서 합니다.initializer는 initializer입니다.을 사용법
또 다른 예는 할당 중에는 할 수 없는 작업을 나중에 수행하는 것입니다.
private static Properties config = new Properties();
static {
try {
config.load(Thread.currentThread().getClassLoader().getResourceAsStream("config.properties");
} catch (IOException e) {
throw new ExceptionInInitializerError("Cannot load properties file.", e);
}
}
, 모든 JDBC 도 JDBC 를 합니다.static
하여 initializer에 합니다.DriverManager
이것과 이 답을 보세요.
라고 말할 수 것 같다.static block
당신이 할 수 일은 .static
차단하고 다른 어떤 것도 하지 않습니다.
여기에 게재된 예시를 재사용하기 위해.
은 이 코드를 사용하지 않고 할 수 .static
이니셜라이저
법:1: 포 methodstatic
private static final HashMap<String, String> MAP;
static {
MAP.put("banana", "honey");
MAP.put("peanut butter", "jelly");
MAP.put("rice", "beans");
}
법2: 포2를 사용하지 않음static
private static final HashMap<String, String> MAP = getMap();
private static HashMap<String, String> getMap()
{
HashMap<String, String> ret = new HashMap<>();
ret.put("banana", "honey");
ret.put("peanut butter", "jelly");
ret.put("rice", "beans");
return ret;
}
이것이 존재해야 하는 실제 이유는 다음과 같습니다.
- , " " "
static final
가 발생할 수 - , " " "
static final
된 을 가진
사람들은 사용하는 경향이 있다.static {}
블록은 특정 클래스(예: JDBC 드라이버)가 로드되었는지 확인하는 등 클래스가 런타임 내에서 종속되는 것을 초기화하는 편리한 방법입니다.으로도 할 수 한 두 는 ', 하다, 하다, 하다'와할 수 있습니다.static {}
개체가 정적 블록에 구성되기 전에 클래스에 대해 코드 비트를 한 번 실행할 수 있습니다.
예.
class A {
static int var1 = 6;
static int var2 = 9;
static int var3;
static long var4;
static Date date1;
static Date date2;
static {
date1 = new Date();
for(int cnt = 0; cnt < var2; cnt++){
var3 += var1;
}
System.out.println("End first static init: " + new Date());
}
}
스태틱 블록이 스태틱필드에만 액세스 할 수 있다고 생각하는 것은 일반적인 오해입니다.이를 위해 실제 프로젝트에서 자주 사용하는 코드(약간 다른 문맥의 다른 답변에서 부분적으로 복사)를 아래에 나타냅니다.
public enum Language {
ENGLISH("eng", "en", "en_GB", "en_US"),
GERMAN("de", "ge"),
CROATIAN("hr", "cro"),
RUSSIAN("ru"),
BELGIAN("be",";-)");
static final private Map<String,Language> ALIAS_MAP = new HashMap<String,Language>();
static {
for (Language l:Language.values()) {
// ignoring the case by normalizing to uppercase
ALIAS_MAP.put(l.name().toUpperCase(),l);
for (String alias:l.aliases) ALIAS_MAP.put(alias.toUpperCase(),l);
}
}
static public boolean has(String value) {
// ignoring the case by normalizing to uppercase
return ALIAS_MAP.containsKey(value.toUpper());
}
static public Language fromString(String value) {
if (value == null) throw new NullPointerException("alias null");
Language l = ALIAS_MAP.get(value);
if (l == null) throw new IllegalArgumentException("Not an alias: "+value);
return l;
}
private List<String> aliases;
private Language(String... aliases) {
this.aliases = Arrays.asList(aliases);
}
}
Initializer)를 유지하기 위해 됩니다.ALIAS_MAP
에일리어스 세트를 원래 열거형으로 매핑합니다.은, 「으로서 「Built-in value Of」라고 하는 값 Of 에 되는 것을 으로 하고 .Enum
그 자체입니다.
와 같이 """ 합니다.private
들 fieldaliases
중요한 것은, 이 점에 주의해 주세요.static
에 이미 할수 있습니다.Enum
(예: ( value ( ( (:ENGLISH
이는 타입의 경우 초기화 및 실행순서가 다음과 같이 되어 있기 때문입니다.static private
보다 앞의 되었습니다.static
블록이 호출되었습니다.
Enum
암시적 정적 필드인 상수입니다.이렇게 하려면 Enum 생성자 및 인스턴스 블록과 인스턴스 초기화도 먼저 수행해야 합니다.static
발생 순서대로 정적 필드를 차단하고 초기화합니다.
가 어긋난 전)static
블록)은 주의할 필요가 있습니다., 싱글톤과, 합니다.
public class Foo {
static { System.out.println("Static Block 1"); }
public static final Foo FOO = new Foo();
static { System.out.println("Static Block 2"); }
public Foo() { System.out.println("Constructor"); }
static public void main(String p[]) {
System.out.println("In Main");
new Foo();
}
}
이 출력은 다음과 같습니다.
Static Block 1
Constructor
Static Block 2
In Main
Constructor
스태틱 초기화는 컨스트럭터 앞이나 다음 이후에도 실제로 발생할 수 있습니다.
메인 메서드에서 Foo에 액세스하는 것만으로 클래스가 로드되고 정적 초기화가 시작됩니다.그러나 Static 초기화의 일부로서 다시 static 필드의 컨스트럭터를 호출하고 그 후 static 초기화를 재개하여 메인 메서드 내에서 호출된 컨스트럭터를 완료합니다.나는 우리가 정상적인 코딩에서는 다루지 않아도 되는 다소 복잡한 상황입니다.
이에 대한 자세한 내용은 "유효한 Java" 책을 참조하십시오.
정적 필드(클래스의 인스턴스가 아닌 클래스에 속하기 때문에 "class variable"이라고도 합니다.즉, 어떤 오브젝트에도 속하지 않고 클래스에 관련지어져 있기 때문에 "class variable"이라고도 불립니다)가 있어 초기화할 필요가 있습니다.따라서 이 클래스의 인스턴스를 만들지 않고 이 스태틱필드를 조작하는 경우는, 다음의 3개의 방법으로 실행할 수 있습니다.
1- 변수를 선언할 때 초기화하기만 하면 됩니다.
static int x = 3;
2- 정적 초기화 블록:
static int x;
static {
x=3;
}
3- 클래스 변수에 액세스하여 초기화하는 클래스 메서드(static 메서드)가 있습니다.이것은 위의 스태틱블록의 대체 수단입니다.프라이빗 스태틱 메서드를 쓸 수 있습니다.
public static int x=initializeX();
private static int initializeX(){
return 3;
}
정적 방법 대신 정적 초기화 블록을 사용하는 이유는 무엇입니까?
그것은 당신의 프로그램에 필요한 것에 달려있다.그러나 정적 초기화 블록은 한 번 호출되며 클래스 메서드의 유일한 장점은 클래스 변수를 다시 초기화할 필요가 있는 경우 나중에 재사용할 수 있다는 것입니다.
프로그램에 복잡한 어레이가 있다고 가정해 보겠습니다.예를 들어 루프에 사용)를 초기화하면 이 배열의 값이 프로그램 전체에서 변경되지만 어느 시점에서 다시 초기화(초기값으로 돌아가기)해야 합니다.이 경우 프라이빗 스태틱메서드를 호출할 수 있습니다.프로그램에서 값을 다시 초기화할 필요가 없는 경우 정적 블록만 사용할 수 있으며 나중에 프로그램에서 사용하지 않을 것이기 때문에 정적 메서드는 필요하지 않습니다.
주의: 정적 블록은 코드에 표시되는 순서대로 호출됩니다.
예 1:
class A{
public static int a =f();
// this is a static method
private static int f(){
return 3;
}
// this is a static block
static {
a=5;
}
public static void main(String args[]) {
// As I mentioned, you do not need to create an instance of the class to use the class variable
System.out.print(A.a); // this will print 5
}
}
예 2:
class A{
static {
a=5;
}
public static int a =f();
private static int f(){
return 3;
}
public static void main(String args[]) {
System.out.print(A.a); // this will print 3
}
}
가 있는 는, 「」를 .static {...}
이치노
예를 들어 스태틱멤버를 컨피규레이션파일 또는 데이터베이스에 저장되어 있는 값으로 설정해야 하는 경우.
, 스태틱에 합니다.Map
초기 멤버 선언에 이러한 값을 추가할 수 없습니다.
보충으로서 @Pointy가 말한 것처럼
"static" 섹션의 코드는 클래스의 인스턴스가 생성되기 전(및 다른 곳에서 스태틱메서드가 호출되기 전) 클래스 로드 시 실행됩니다.
해서 '더하다'를 넣게 .System.loadLibrary("I_am_native_library")
이치노
static{
System.loadLibrary("I_am_a_library");
}
관련 라이브러리가 메모리에 로드되기 전에 네이티브 메서드가 호출되지 않음을 보증합니다.
oracle의 loadLibrary에 따르면:
이 메서드가 같은 라이브러리 이름으로 여러 번 호출될 경우 두 번째 콜과 후속 콜은 무시됩니다.
따라서 System.loadLibrary를 넣는 것은 라이브러리가 여러 번 로드되는 것을 피하기 위해 사용되지 않습니다.
클래스 가 '어플리케이션 클래스'로 .java.class.Class
실행될 입니다.이때 정적 블록이 실행됩니다.을 사용하다
public class Main {
private static int myInt;
static {
myInt = 1;
System.out.println("myInt is 1");
}
// needed only to run this class
public static void main(String[] args) {
}
}
콘솔에 "myInt is 1"이라고 출력합니다.클래스는 인스턴스화하지 않았습니다.
static int B,H;
static boolean flag = true;
static{
Scanner scan = new Scanner(System.in);
B = scan.nextInt();
scan.nextLine();
H = scan.nextInt();
if(B < 0 || H < 0){
flag = false;
System.out.println("java.lang.Exception: Breadth and height must be positive");
}
}
static block은 static data member를 다이내믹하게 초기화하기 위한 모든 기술에 사용됩니다. 또는 static data member static block이 사용되고 있다고 말할 수 있습니다.비정적 데이터 멤버 초기화의 경우 컨스트럭터는 있지만 스태틱 데이터 멤버를 동적으로 초기화할 수 있는 장소는 없기 때문입니다.
Eg:-class Solution{
// static int x=10;
static int x;
static{
try{
x=System.out.println();
}
catch(Exception e){}
}
}
class Solution1{
public static void main(String a[]){
System.out.println(Solution.x);
}
}
이제 정적 int x가 동적으로 초기화됩니다.Bcoz는 컴파일러가 Solution.x로 이동할 때 솔루션 클래스와 정적 블록 로드를 로드합니다.따라서 정적 데이터 구성원을 동적으로 초기화할 수 있습니다.
}
언급URL : https://stackoverflow.com/questions/2420389/static-initialization-blocks
'programing' 카테고리의 다른 글
Vux with Jest - 이거.$store.getters.는 함수가 아닙니다. (0) | 2022.07.15 |
---|---|
Vuej와 Vuex를 사용하여 품목 가격을 합산하여 총 가격을 표시하는 방법 (0) | 2022.07.15 |
Vuetify v-select onchange 이벤트가 현재 대신 이전에 선택한 값을 반환함 (0) | 2022.07.15 |
여러 컴포넌트의 값 전송 (0) | 2022.07.15 |
C에서 단항 더하기(+) 연산자의 목적은 무엇입니까? (0) | 2022.07.15 |