[Java] 클래스 멤버 (변수 쳅터와 내용 비슷)

JD_S·2022년 11월 22일
0

Java

목록 보기
17/21

필드

필드의 구분

클래스 필드란 클래스에 포함된 변수를 의미한다. 클래스 내에서 필드는 선언된 위치에 따라 다음과 같이 구분된다.

  • 클래스 변수(static variable)
  • 인스턴스 변수(instance variable)
  • 지역 변수(local variabel)
class Car {
  static int modelOutput;	//클래스 변수
  String modelName;			//인스턴스 변수
  
  void method() {
    int something = 10;		//지역 변수
  }
}

클래스 변수와 인스턴스 변수는 초기화를 하지 않아도 변수의 타입에 맞게 자동으로 초기화될 것이다. 하지만 지역 변수는 사용하기 전에 초기화하지 않으면, 자바 컴파일러가 오류를 발생시킨다.

자바에서 클래스 변수와 인스턴스 변수의 초깃값은 다음과 같다.

클래스 변수와 인스턴스 변수

클래스 영역에 위치한 변수 중에서는 static 키워드를 가지는 변수를 클래스 변수라고 한다. 그리고 클래스 영역에 위치한 변수 중 static 키워드를 가지지 않는 변수는 인스턴스 변수라고 한다. 또한, 메서드나 생성자, 초기화 블럭 내에 위치한 변수를 지역 변수라고 한다.

이렇게 선언된 위치에 따라 구분되는 변수는 생성 및 소멸 시기, 저장되는 메모리 공간과 사용 방법까지도 서로 다르다.

클래스 변수는 인스턴스를 생성하지 않고도 바로 사용할 수 있다. 따라서 이러한 클래스 변수를 공유 변수(shared variable)라고도 한다.

이러한 클래스 변수는 해당 클래스의 모든 인스턴스가 공유해야 하는 값을 유지하기 위해 사용된다. 반면에 인스턴스 변수는 인스턴스마다 가져야 하는 고유한 값을 유지하기 위해 사용된다.

아래 코드는 클래스에 여러 가지 종류의 변수를 생성하고 참조하는 코드이다.

class Field {
  static int classVar = 10;	//클래스 변수 선언
  int instanceVar = 20;		//인스턴스 변수 선언
}

public class Member01 {
  public static void main(String[] args) {
    int var = 30;					//지역 변수 선언
    System.out.println(var + "\n");	//지역 변수 참조
    
    Field myField1 = new Field();	//인스턴스 생성
    Field myField2 = new Field();	//인스턴스 생성
    
    System.out.println(Field.classVar);	//클래스 변수 참조
    System.out.println(myField1.classVar);
    System.out.println(myField2.classVar + "\n");
    
    myField1.classVar = 100;		//클래스 변수의 값을 변경
    
    System.out.println(Field.classVar);	//클래스 변수 참조
    System.out.println(myField1.classVar);
    System.out.println(myField2.classVar + "\n");
    
    System.out.println(myField1.instanceVar);	//인스턴스 변수 참조
    System.out.println(myField2.instanceVar + "\n");
    
    myField1.instanceVar = 200;		//인스턴스 변수의 값을 변경
    
    System.out.println(myField1.instanceVar);	//인스턴스 변수 참조
    System.out.println(myField2.instanceVar);
  }
}

결과
30
    
10
10
10
    
100
100
100
    
20
20
    
200
20

위의 코드를 통해 클래스 변수는 생성된 모든 인스턴스가 같은 값을 공유하는 것을 확인할 수 있다. 하지만 인스턴스 변수는 각 인스턴스마다 고유한 값을 가지는 것을 확인할 수 있다.

메서드

메서드의 구분

클래스 메서드란 어떠한 작업을 수행하기 위한 명령문의 집합이라고 할 수 있다. 클래스 내에서 메서드는 static 키워드의 여부에 따라 다음과 같이 구분된다.

  • 클래스 메서드
  • 인스턴스 메서드
class Car {
  boolean door; //인스턴스 변수
  void openDoor() { //인스턴스 메서드
    door = true;
  }
  
  static void toggleDoor(boolean d) { //클래스 메서드
    return !d;
  }
}

클래스 메서드와 인스턴스 메서드

위와 같이 static 키워드를 가지는 메서드를 클래스 메서드라고 한다. 또한, static 키워드를 가지지 않는 메서드는 인스턴스 메서드라고 한다.

클래스 메서드는 클래스 변수와 마찬가지로 인스턴스를 생성하지 않고도 바로 사용할 수 있다.
따라서 클래스 메서드는 내부에서 인스턴스 변수를 사용할 수 없다.
그러므로 메서드 내부에서 인스턴스 변수나 인스턴스 메서드를 사용하지 않는 메서드를 클래스 메서드로 정의하는 것이 일반적이다.

아래 코드는 클래스의 메서드를 종류별로 생성하고 접근하는 코드이다.

class Method {
  int a = 10, b = 20; //인스턴스 변수
  int add() { return a + b; } //인스턴스 메서드
  
  static int add(int x, int y) { return x + y; } //클래스 메서드
}

public class Member02 {
  public static void main(String[] args) {
    System.out.println(Method.add(20, 30)); //클래스 메서드의 호출
    Method myMethod = new Method(); //인스턴스 생성
    System.out.println(myMethod.add()); //인스턴스 메서드의 호출
  }
}

결과
50
30

위의 코드처럼 클래스 메서드는 인스턴스 변수를 사용하지 않고, 전달된 매개변수만으로 동작하는 메서드이다.

초기화 블럭

필드의 초기화

자바에서 필드는 초기화하지 않아도 변수의 타입에 맞는 초깃값으로 자동으로 초기화 된다.
하지만 지역 변수와 마찬가지로 적절한 값으로 초기화한 후에 사용하는 것이 좋다.

이러한 필드는 지역 변수와 달리 여러 가지 방법으로 초기화할 수 있다.
자바에서는 필드를 초기화하기 위해 다음과 같은 방법들을 제공한다.

  • 명시적 초기화
  • 생성자를 이용한 초기화
  • 초기화 블럭을 이용한 초기화

명시적 초기화는 지역 변수를 초기화하는 방법과 마찬가지로 필드를 선언과 동시에 초기화하는 방법이다.

class Field {
  static int classVar = 10; //클래스 변수의 명시적 초기화
  int instanceVar = 20; //인스턴스 변수의 명시적 초기화
}

생성자를 이용한 초기화는 객체의 생성과 동시에 필드를 초기화하는 방법이다.
따라서 생성자를 이용한 초기화는 인스턴스를 생성할 때까지 필드를 초기화할 수 없다.

초기화 블럭

필드를 초기화하는 마지막 방법으로는 자바에서 제공하는 초기화 블럭을 이용하는 방법이 있다.
초기화 블럭이란 클래스 필드의 초기화만을 담당하는 중괄호({})로 둘러싸인 블럭을 의미한다.
초기화 블럭은 생성자보다 먼저 호출되며, static 키워드의 유무에 따라 다음과 같이 구분할 수 있다.

  • 인스턴스 초기화 블럭
  • 클래스 초기화 블럭

이러한 초기화 블럭에는 다양한 명령문 및 제어문을 사용할 수 있으므로, 복잡한 초기화를 해야 할 경우 유용하게 사용된다.

인스턴스 초기화 블럭

인스턴스 초기화 블럭은 단순히 중괄호({})만을 사용하여 정의할 수 있다.
이러한 인스턴스 초기화 블럭은 생성자와 마찬가지로 인스턴스가 생성될 때마다 실행된다.
하지만 언제나 인스턴스 초기화 블럭이 생성자보다 먼저 실행된다.

생성자와 인스턴스 초기화 블록의 차이는 거의 없으므로 인스턴스 초기화 블럭은 잘 사용되지 않는다.
단, 여러 개의 생성자가 있으면 모든 생성자에게 공통으로 수행되어야 할 코드를 인스턴스 초기화 블럭에 포함하여 코드의 중복을 막을 수 있다.

아래 코드는 인스턴스 초기화 블럭을 이용하여 여러 생성자에게 공통된 부분을 분리하는 코드이다.

class Car {
  private String modelName;
  private int modelYear;
  private String color;
  private int maxSpeed;
  private int currentSpeed;
  
  {//인스턴스 초기화 블럭
     this.currentSpeed = 0; 
  }
  
  Car() {}
  
  Car(String modelName, int modelYear, String color, int maxSpeed) {
    this.modelName = modelName;
    this.modelYear = modelYear;
    this.color = color;
    this.maxSpeed = maxSpeed;
  }
  
  public int getSpeed() {
    return currentSpeed;
  }
}

public class Member03 {
  public static void main(String[] args) {
    Car myCar = new Car(); //인스턴스 생성
    System.out.println(myCar.getSpeed()); //인스턴스 메서드의 호출
  }
}

결과
0

클래스 초기화 블럭

클래스 초기화 블럭은 인스턴스 초기화 블럭에 static 키워드를 추가하여 정의할 수 있다.
이러한 클래스 초기화 블럭은 클래스가 처음으로 메모리에 로딩될 때 단 한 번만 실행된다.

클래스 초기화 블럭은 생성자나 인스턴스 초기화 블럭으로는 수행할 수 없는 클래스 변수의 초기화를 수행할 때 사용한다.

아래 코드는 클래스 초기화 블럭을 이용하여 클래스 변수를 초기화하는 코드이다.

class InitBlock {
  static int classVar; //클래스 변수
  int instanceVar; //인스턴스 변수
  
  static { //클래스 초기화 블럭을 이용한 초기화
    classVar = 10;
  }
}

public class Member04 {
  public static void main(String[] args) {
    System.out.println(InitBlock.classVar); //클래스 변수에 접근
  }
}

결과
10

필드의 초기화 순서

클래스의 필드는 앞서 살펴본 것과 같이 다양한 방법으로 초기화할 수 있다.
따라서 같은 필드가 여러 번 초기화될 가능성이 있다.

자바에서 필드는 다음과 같은 순서로 초기화된다.

  1. 클래스 변수 : 기본값 -> 명시적 초기화 -> 클래스 초기화 블럭
  2. 인스턴스 변수 : 기본값 -> 명시적 초기화 -> 인스턴스 초기화 블럭 -> 생성자

아래 코드는 클래스 변수와 인스턴스 변수가 초기화되는 순서를 보여주는 코드이다.

class InitBlock {
  static int classVar = 10; //클래스 변수의 명시적 초기화
  int instanceVar = 10; //인스턴스 변수의 명시적 초기화
  static { classVar = 20; } //클래스 초기화 블럭을 이용한 초기화
  { instanceVar = 20; } //인스턴스 초기화 블럭을 이용한 초기화
  InitBlock() { instanceVar = 30; } //생성자를 이용한 초기화
}

public class Member05 {
  public static void main(String[] args) {
    System.out.println(InitBlock.classVar);
    InitBlock myInit = new InitBlock();
    System.out.println(myInit.instanceVar);
  }
}

결과
20
30

설명은 아래 링크(변수 쳅터)와 유사하다.

https://velog.io/@my_id/Java-%EB%B3%80%EC%88%98

Reference

profile
Whatever does not destroy me makes me stronger.

0개의 댓글