DevBoi

[Java] static block 및 instance block 본문

Language/[Java]

[Java] static block 및 instance block

HiSmith 2023. 6. 26. 14:05
반응형

뭐든 그냥 쓰는 것 만큼 멍청한건 없다.

이제 자주쓰지만 그동안 정확히 왜 쓰는지 잘 모를 만한 것에 포스팅 하겠다.

 

1) static block 

- 클래스가 로딩되고, 클래스 변수가 준비된 후 자동으로 실행되는 블록

- 한 클래스안에 여러개의 static 블록을 넣을 수 있따.

- 선언된 스태틱 블록 대로 실행된다.

 

용도 : 주로 클래스 변수를 초기화 시키는 코드를 둔다.

아래와 같은 코드가 있다고 가정하자.

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class BikeShop {
  public static String name = "b1";
  static{
    System.out.println("static1");
    name = "b2";
  }
  static{
    System.out.println("static2");
    name = "b3";
  }
  public String getName(){
    return this.name;
  }
}
static1
static2

클래스를 호출하면 스태틱 블록이 차례로 호출이 된다.

또한 이름을 출력하면, b3가 된다.

@NoArgsConstructor(access = AccessLevel.PRIVATE)

위의 역할은 파라미터가 없는 기본생성자를 생성해준다.다만  액세스 레벨이 프라이빗이니까

외부에서 기본 생성자로 생성을 못하게 해준다. 즉 값이 불변하는 걸 보장해준다.

 

실행순서는 이렇다.

-클래스가 로딩된다.

-클래스 변수가 있으면 메모리를 생성한다.

-static 블록이 선언된 순서대로 실행된다.

 

클래스 로딩 절차는 이렇다.

>JRE라이브러리에서 클래스를 찾는다.

>없으면, ClassPath 환경 변수에 지정된 폴더에서 클래스를 찾는다.

>찾았으면, 그 클래스 파일이 올바른 바이트 코드인지검증한다.

>올바른 바이트코드라면, Method Area영역으로 파일을 로딩한다.

>클래스 블록이 있으면 순서대로 그 블록을 실행한다.

>클래스 안에 static bloack이 있으면 순서대로 그 블록을 실행한다.

 

 

위와 같은 순서로 블록이 실행되기 떄문에, 해당 스태틱 블록은 여러번 실행되지 않는다.(여러번 호출하더라도)

 

그러면 이제 여러번 호출하면, 계속 실행되는 인스턴스 블록에 대해서 살펴보자

 

2) instance block

- 인스턴스가 생성된 후 자동으로 실행하는 블록

- 한 클래스안에 여러개의 인스턴스 블록을 넣을 수 있다.

- 용도:

인스턴스 변수를 초기화 시키는 코드를 둔다.

어떤 생성자가 호출되든 그 전에 공통으로 초기화 시키고 싶은 작업이 있다면 

인스턴스 블록에서 처리하면된다.

 

@NoArgsConstructor
public  class BikeShop {
  @Getter
   String name = "b1";
  {
    System.out.print("hi instance");
    name = "newins";
  }
}

 

이럴 경우, 인스턴스가 생성될때마다 인스턴스 블록이 실행되고

GetName의 경우 인스턴스 블록에서지정한 값이 리턴된다.

생성자가 여러개이지만 공통으로 처리할 메소드에 따라 사용하면 코드의 량을 줄여줄 수 있다.

 

자바 레코드 패턴을 쓰면 컴팩트 생성자를 주로 쓴다.

이를 빌더랑 결합하면 아래와 같이 사용가능하다.

public record RecordCarsDto(List<String> values, int speed) {

  @Builder
  RecordCarsDto(List<String> values, int speed) { 
    if (Objects.isNull(values)) {
      values = new ArrayList<>();
    }
    if (Objects.isNull(speed)) {
      speed = 10;
    }
    this.values = values;
    this.speed = speed;
  }
}

 

 

이 방법은 레코드를 쓰지 않는경우, builder.default와 동일하다.

builder.default는 빌더 패턴으로 만들때 특정 값으로 초기화하고싶은 경우 사용한다.

아래의 경우에 해당 빌더로 만드는 경우, name을 자동 지정해준다. (값이 없다면)

@ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Pojo {

    @Builder.Default
    private String name = "기본이름";
    private String nickname;
    private List<PojoTwo> pojoTwos = new ArrayList<PojoTwo>();

}

 

 

반응형