Java/Java의 정석

Chapter 06 객체지향 프로그래밍 I

계란💕 2022. 2. 22. 00:05

1. 객체지향언어

  - 코드의 재사용성 높음

  - 유지보수가 쉽고 중복 코드 제거, 빠른 변화를 쫓아간다.

  - 객체지향언어 = 프로그래밍 언어 + 객체지향개념(규칙) .. 규칙은 외우기

  - 핵심 개념 (자바의 대표적인 4가지 특징)

    1) 캡슐화(Encapsulaion): 객체와 객체간의 의사소통을 위해 필요한 정보만을 노출한다. (실제 내부의 구현 정보는 숨긴다.)

    2) 상속(Inheritance): 상위 클래스와 하위 클래스가 계층적인 구조를 가진다.

                               상위 클래스의 공통된 특성을 하위클래스만다 반복 없이 한 번만 기술한다. 재사용성의 효과가 있다.

    3) 추상화(Abstraction): 실세계의 객체에서 필요한 부분만을 간결하고 이해하기 쉬운 클래스로 만든다. (속성행동으로 구체화)

    4) 다형성(Polumorphism): 외부에 보이는 모습은 한 가지지만 실질적으로 쓰이는 기능은 여러 가지 역할을 수행한다.

                                      ex) 오버로딩(생성자 구현할 때 주로 쓴다.), 오버라이딩(오버라이딩은 상속에 의해 많이 이뤄진다.)

 

  Note) 객체지향 프로그래밍 

  - 클래스를 생성하고 클래스로부터 객체를 만들어 객체간의 상호작용을 이용하여 주어진 문제를 해결하는 방식이다. 

  - 데이터인 필드와 절차인 메서드를 하나로 묶은 클래스 단위의 프로그램

 

  Note) 절차지향 프로그래밍 (절차적/ 구조적 프로그래밍)

  - 객체지향언어 개념이 나오면서 기존 프로그래밍 방식을 표현하기 위해 사용한다.

  - 일련의 동작(모듈, 함수)를 순서에 맞게 실행한다.

  - 소프트웨어의 규모가 커지면서 기능들이 복잡해지고 추가 개발이나 유지, 보수에 어려움이 생겼다.

  

  1.1 객체지향언어의 역사

  1.2 객체지향언어

  1) 코드의 재사용성 높음

  2) 코드의 관리가 용이

  3) 신뢰성 높은 프로그래밍을 가능하게 함.

 

 

2. 클래스와 객체 

  2.1 클래스와 객체의 정의와 용도

    Def) 클래스: 클래스란 객체를 정의해 놓은 것

    - 용도: 객체를 생성하는데 사용한다.

    - 객체를 만들기 위해 객체의 다양한 특성을 표현할 수 있는 모형인 클래스가 필요하다.

 

    Def) 객체: 실제로 존재하는 것, 사물, 개념

    - 용도: 객체가 가지고 있는 기능과 속성에 따라 다르다.

    - 객체 = 속성(변수) + 기능(메서드)

 

  2.2 객체와 인스턴스 (거의 같다고 본다.)

    Def) 객체 : 모든 인스턴스를 대표하는 일반적 용어 - 객체는 instance value의 묶음이다.

    - 현실 세계의 사물이나 개념을 시스템에서 사용하기 위해 현실 세계를 자연스럽게 표현하여  이용할 수 있도록 만든 소프트 웨어 모델

    - 객체 = 속성(attribute, properties - 객체를 구별하는 특성 / 필드 ) + 행동(message, behaviors, method - 행위를 기술 / 메서드)

 

    Def) 인스턴스: 특정 클래스로부터 생성된 객체 ex) Tv인스턴스

      - 클래스 --(인스턴스화)--> 인스턴스(객체)

 

  2.3 객체의 구성요소 - 속성과 기능

  - 속성: 멤버변수, 특성, 필드, 상태 

    -> 필드는 값을 저장하기 위해 선언, 정의

    -> 메서드는 기능을 수행하기 위해 선언, 정의

  - 기능: 메서드, 함수, 행위

 

  2.4 인스턴스의 생성과 사용

  1) 참조변수 선언

  2) 인스턴스를 생성 후, 생성된 Tv인스턴스의 주소를 t에 저장

  3) 객체의 사용 (메서드 호출)

  - 하나의  인스턴스를 여러 개의 참조변수가 가지키는 경우? 가능하다.

  - 여러 인스턴스를 하나의 참조변수가 가리키는 경우? 불가능하다.

 

  2.5 객체의 배열

  - 객체 배열 = 참조변수 배열

  - Tv [] tvArr =new TV[3]; 객체 베열을 만들면 참조변수의 기본값: null로 초기화

  Ex)

<hide/>
package javaStudy;
public class TvTest4 {
	public static void main(String[] args) {
		Tv [] tvArr = new Tv[3];  // 길이가 3인 tvArr 배열
		for(int i = 0; i < tvArr.length; ++i) {
			tvArr[i] = new Tv();
			tvArr[i].channel = i + 10;		// tvArr[i]의 channel에 i + 10에 저장
		}
		for(int i = 0; i < tvArr.length; ++i) {
			tvArr[i].channelUp();  // tvArr[i]의 메서드를 호출, 채널이 1증가
			System.out.printf("tvArr[%d].channel= %d%n", i, tvArr[i].channel );
		}
	}
}
class Tv{
	String color;		// 색상
	boolean power;		// 전원상태(on/off)
	int channel;		// 채널
	void power() {power = ! power;}
	void channelUp() {++channel;}
	void chanelDown() {--channel;}
	
}

  Note) 실행 결과

 

  2.6 클래스의 또 다른 정의

  Def) 클래스

    - 설계도

    - 데이터 + 함수

     - 사용자 정의 타입: 원하는 타입을 직접 만들 수 있다.

 

  1) 변수: 하나의 데이터를 저장할 수 있는 공간

  2) 배열: "같은 종류"의 여러 데이터를 하나로 저장할 수 있는 공간

  3) 구조체: 서로 관련된 여러 데이터(종류에 관계 없다)를 하나로 저장할 수 있는 공간

  4) 클래스: 데이터와 함수의 결합 (구조체 + 함수)

 

3. 변수와 메서드

  3.1 선언위치에 따른 변수의 종류

    1) 클래스 영역에 선언 - iv. cv

      - 클래스 영역에는 변수/ 메서드 선언만 가능하다.

    2) 메서드 영역 - lv

 

  - 인스턴스 변수 (iv): 인스턴스가 생성됐을 때, iv가 만들어진다.  - 개별 속성

  - 클래스 변수 (cv, "static" 변수, 공유변수, static iv): 클래스가 메모리에 올라갈 때, cv가 생성된다. - 공통 속성

  - 지역 변수 (local variable) : 메서드 안에서만 유효하다.

  - cv와 iv의 차이점: iv는 객체 생성해야만 만들어지고, cv(만들지 않아도 아무 때나 쓸 수 있다)는 객체 생성 필요없다. 

  - 객체는 iv의 묶음이다.

 

  3.2 클래스 변수(cv)와 인스턴스 변수(iv)

  Ex) 카드 게임의 카드를 클래스로 정의하자. 카드 클래스를 작성하기 위해 카드 속성과 기능을 알아내야 한다.

  - 폭과 높이는 모든 카드가 같다 -> cv (static iv) => 공통 속성

  - 무늬와 숫자는 각각 다르다 -> iv  => 개별 속성

    -> cv는 (참조변수).height가 아니라 (클래스명).height를 쓰는 것이 정확하다. 

    -> c1.height = 80; 이라고 하면 c1을 포함한 모든 카드의 height 값이 80으로 바뀐다.

 

  3.3 메서드

  Def) 메서드: 문장들을 작업 단위로 묶어 놓은 것, 값을 받아서 처리하고 결과를 반환(출력)한다.

    - 함수와 거의 같은 말이다

    - 메서드는 클래스 안에 반드시 들어가 있어야하고 함수는 독립적이다.

    - 메서드 = 선언부 + 구현부

    - 반환타입 메서드이름(타입 변수명, 타입 변수명, ...)

    - 메서드는 클래스 영역에만 정의 가능하다.

    - 구현부

      -> 지역변수(lv): 메서드 내에 선언된 변수 (다른 메서드에 이름이 같은 변수가 있어도 상관없다. )  

    - Math.sqrt(): 제곱근을 구하는 메서드

 

  3.4 메서드의 선언과 구현

  - 메서드는 선언부(header, 머리), 구현부(body, 몸통)으로 이뤄진다.

 

  3.5 메서드의 실행흐름

    1) 인스턴스 생성

    2) 메서드 호출

 

  3.6 return문

    - return문: 실행중인 메서드 종료하고 호출한 곳으로 돌아간다.

      -> 반환타입이 void가 아니면 반드시 return문이 필요하다. 

  - 메서드의 유효성 검사: 메서드의 구현부를 작성할 때, 매개변수의 값이 적절한지 확인해야 한다.

<hide/>
float divide(int x, int y) {
	// 작업을 하기 전에 나누는 수(y)가 0인지 확인한다. 
	if(y == 0) {
		System.out.println("0으로 나눌 수 없습니다.");
		return 0; // 매개변수가 유효하지 않으므로 메서드를 종료한다. 
	}
	return x / (float)y;
}

  - divide메서드는 매개변수 x를 y로 나눈 결과를 float타입으로 반환하는데 0으로 나누는 건 금지되어있다.

  - 그러므로 계산전에 y가 0이면 return문을 이용해서 작업 중단하고 빠져나가야한다.

 

  3.7 JVM의 메모리 구조

  - 응용프로그램이 실행되면 JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당 받고

  - JVM은 이 메모리를 용도에 따라 여러 영역으로 나눠 관리한다.

 

  1) 호출 스택( call stack 또는 execution stack )

      - 밑이 막힌 상자, 위에 차곡차곡 쌓인다

      - 메서드 수행에 필요한 메모리가 제공되는 공간

      - 메서드가 호출되면 호출스택에 메모리 할당, 종료되면 해제(스택에서 제거)

      - 호출 스택의 제일 위에 있는 메서드가 현재 실행 중인 메서드이다.

      - 아래에 있는 메서드가 바로 위의 메서드를 호출한 메서드이다.

 

  2) 메서드 영역

    - 프로그램 실행 중, 어떤 클래스가 사용되면 JVM은 해당 클래스의 클래스 파일(*.class)을 읽어서 분석하여 클

    - 래스에 대한 정보를 메서드 영역에 저장한다. 클래스 변수도 함께 저장.

 

  3) 힙(heap)

    - 인스턴스가 생성되는 공간, 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 저장된다. 

    - 즉, 인스턴스 변수들이 생성되는 공간이다. 

 

  3.8 기본형 매개변수와 참조형 매개변수

  - 기본형 매개변수: 변수의 값을 읽기만 할 수 있다.

  Ex)

<hide/>
package javaStudy;
class Data { int x; }
public class PrimitiveParamEx {
	public static void main(String[] args) {
		Data d = new Data();
		d.x = 10;
		System.out.println("main() : x = " + d.x);
		
		change(d.x);
		System.out.println("Afterchange(d.x)");
		System.out.println("main() : x = " + d.x);	
	}
	static void change(int x) { 
		x = 1000;
		System.out.println("change) : x = " + x );
	}
}

  Note) 실행 결과

 

  - change 메서드에서 main으로부터 넘겨받은 d.x의 값을 1000으로  변경했는데도 main메서드에서는 d.x그대로.

  1) change 메서드가 호출되면서 'd.x'가 change메서드의 매개변수 x에 복사된다.

  2) change메서드에서 x의 값을 1000으로 변경 

  3) change메서드가 종료되면서 매개변수 x는 스택에서 제거된다.

    -> d.x의 값이 변경된 것이 아니라 change메서드의 매개변수 x값이 변경된 것이다.

    -> 기본형 매개변수는 변수에 저장된 값만 읽을 수 있지 변경할 수는 없다. 

 

  - 참조형 매개변수: 변수의 값을 읽고 변경할 수 있다. 

  Ex)

<hide/>
package javaStudy;
class Data { int x; }
public class RefenceParmEx {
	public static void main(String[] args) {
		Data d = new Data();
		d.x = 10;
		System.out.println("main() : x = "+ d.x);
		change(d);
		System.out.println("After change(d) ");
		System.out.println("main() : x = "+ d.x);
	}
	static void change(Data d) {
		d.x = 1000;
		System.out.println("change() : x = "+ d.x);
	}
}

  Note) 실행 결과

  - 기본형 매개변수의 예제와 다르게 change메서드를 호출한 다음, d.x 값이 변경되었다. 

  - change메서드의 매개변수가 참조형이라서 값이 아니라 '값이 저장된 주소'를 change메서드에 넘겨준다.

  - 그렇기 때문에 값을 읽어오는 것 말고도 변경하는 것도 가능하다.

 

  3.9 참조형 반환타입

  - 반환타입이 참조형이면 복사한 객체(의 주소)를 반환한다. 

  - 변수 타입과 반환타입이 일치해야한다.

  - 반환타입이 '참조형'이라는 것은 메서드가 '객체의 주소'를 반환한다는 것을 의미한다. 

 

  3.10 재귀호출(recursive call)

  Def) 재귀호출: 메서드 내부에서 메서드 자신을 다시 호출하는 것

    - 이 때, 재귀호출하는 메서드를 '재귀 메서드'라고 한다. 

    - 재귀호출 하는 이유는? 

      -> 논리적인 간결함 때문

  - StackOverFlowError: 호출  스택의 메모리 한계를 넘게 되면 생기는 오류

 

  3.11 static 메서드와 인스턴스 메서드

  Def) static 메서드(클래스 메서드)

    -> 객체생성없이 '클래스이름, 메서드이름()'으로 호출할 수 있다.

    -> 인스턴스 멤버(iv, im)와 관련 없는 작업을 하는 메서드

    -> 메서드 내에서 인스턴스 변수(iv) 사용 불가

    -> iv가 필요 없다. 즉, 객체가 필요없다.

 

  Def) 인스턴스 메서드  

    -> 인스턴스 생성 후, '참조변수.메서드이름()'으로 호출

    -> 인스턴스 멤버(iv, im)과 관련된 작업을 하는 메서드

    -> 메서드 내에서 인스턴스 변수(iv) 사용가능

    ->  ex) Math.random(), Math.round(), ...(Math: 클래스 이름 )

 

  - 인스턴스 멤버(iv와 im)를 사용하지 않는 메서드에 'static'을 붙인다.

 

  3.12 클래스 멤버와 인스턴스 멤버간의 참조와 호출

  - 인스턴스 메서드(im)는 static메서드를 호출할 수 있다.

  - static메서드는 인스턴스 메서드(im)을 호출할 수 없다. 

    -> 인스턴스메서드는 iv로 작업하는 메서드라 객체가 필요하다.

    -> static메서드(항상 호출가능)

 

 

4. 오버로딩(overoading)

  4.1 메서드 오버로딩이란?

    Def) 한 클래스 안에 같은 이름의 메서드 여러 개를 정의하는 것, 메서드 이름은 같고 매개변수의 타입이 다르다.

    Ex) println(), 매개변수에 int, String, ...모두 가능한 이유

 

  4.2 오버로딩의 조건

    1) 메서드 이름이 같아야 한다.

    2) 매개변수의 개수 또는 타입이 달라야 한다.

    3) 변환 타입은 영향 없다.

 

  4.3 오버로딩의 예

  - 매개변수의 타입은 같고 변수명만 다르면 -> 오버로딩이 아닌 "메서드 중복정의"

  Ex) 오버로딩 예시

<hide/>
long add(int a, long b){ return a + b };
long add(long a, int b){ return a + b };

   - 위 코드에 대해 add(3, 3L)을 호출한다면? -> 위의 메서드 호출

   - 위 코드에 대해 add(3, 3)을 호출한다면? 

    -> 컴파일 에러(Ambiguous, 모호하다. ).. 두 식에 모두 3, 3이 들어갈 수 있기 때문이다.

 

  4.4 오버로딩의 장점

  4.5 가변인자(varargs)와 오버로딩

  - 기존에는 메서드의 매개변수 개수가 고정적이었으나 JDK1.5부터 동적으로 지정해 줄 수 있게 되었다.

  - 이 기능을 '가변인자'라고 한다. "타입.. 변수명"과 같은 형식으로 선언한다. 

  - 가변인자는 매개변수 중 가장 마지막에 선언해야한다. ex) PrintStream클래스의 printf()

 

  Ex) 가변 인자 사용 방법

<hide/>
static String concatenate(String... str){
return null;
}
public static void main(String[] args){
    System.out.println(concatenate());
    System.out.println(concatenate("a"));
    System.out.println(concatenate("a", "b"));
    System.out.println(concatenate(new String[]{"a", "b"}));
}

 

 

 

5. 생성자(Constructor)

  5.1 생성자란?

  Def) 생성자: 인스턴스가 생성될 때마다 자동으로 호출되는 '인스턴스 초기화 메서드'

  - 인스턴스 변수의 초기화 또는 인스턴스 생성시 수행할 작업에 사용

  - 몇 가지 조건을 빼고는 메서드와 같다. (생성자는 반환형이 없다. 한정자와 클래스명만 있으면 된다.)

  - 모든 클래스에는 반드시 생성자가 있어야한다.

    -> 기본 생성자는 만들지 않아도 제공된다. 명시적으로 만드는 것도 가능하다.

    -> 명시적으로 생성자를 만들면 기본 생성자는 사라진다.

  - 생성자의 조건: 생성자 이름은 클래스와 같고, 생성자는 반환값이 없다. 

    -> 하지만, 'void'를 쓸 필요 없다. 

  - 생성자 오버로딩: 하나의 클래스에서 인자가 다르면 생성자를 여러 개 구현 가능하다.

  - 형식

<hide/>
클래스 이름 (타입 변수명, 타입 변수명, ...) {
	// 인스턴스 생성 시 수행될 코드
	// 주로 인스턴스 변수의 초기화 코드를 적는다. 
}

 

   Note) 생성자의 한정자는 항상 public은 아니다.

  - Calendar는 new Calendar() 로 만들 수 없고 Calendar.getInstance()를 통해 객체를 만들 수 있다. (getInstance()는 public)

  - 생성자"Calendar()"가 있지만 protected로 한정되어 있어서 상속 받은 클래스 내에서 사용할 수 있다.

  - 달력의 경우에는 어차피 하나의 객체만 있어도 사용하는데 문제가 없기 때문이다.

 

  5.2 기본 생성자(Default Constructor)

   Def) 기본 생성자: 매개변수가 없는 생성자

  - 클래스에 생성자가 하나도 없는 경우에만 컴파일러는 기본 생성자를 추가한다. 

  - 모든 클래스에는 반드시 하나 이상의 생성자가 있어야 한다. 

  

  5.3 매개변수가 있는 생성자

  Ex) 

<hide/>
package javaStudy;
class Data1 {
	int value;
}
class Data2 {
	int value;
	Data2(int x){
	value = x;
	}
}
public class ConstructorTest {
	public static void main(String[] args) {
		Data1 d1 = new Data1();
		Data2 d2 = new Data2();
	}
}

  Note) 실행 결과

  - Data2에서 생성자 d2를 찾을 수 없다는 에러 메시지가 나타난다.

  - Data2에 생성자 Data2()가 정의되어 있지 않기 때문에 에러가 발생한다. 

 

  - Data1에는 에러가 나지 않는데 Data2에만 발생하는 이유는

    -> Data1에는 정의되어있는 생성자가 하나도 없으므로 컴파일러가 기본 생성자를 추가한다. 

    -> 그러나 Data2에는 이미 생성자 Data2(int x)가 정의되어 있기 때문에 기본 생성자가 추가되지 않는다. 

  - '클래스 내에 생성자가 하나도 없을 때만 컴파일러가 자동으로 생성자를 추가해준다.'

 

  5.4 생성자에서 다른 생성자 호출하기 - this(), this

  - 같은 클래스의 멤버들 간에 서로 호출할 수 있는 것처럼 생성자 간에도 서로 호출이 가능하다.  

  - 아래 조건을 만족시켜야 가능하다.

    1) 생성자의 이름으로 클래스 이름대신 this를 사용한다.

    2) 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 문장에서만 가능하다. 

    (1) this(매개변수) 생성자 (같은 클래스의 다른 생성자를 호출할 때 사용), this생성자는 한 번만 사용 가능

    (2) this: 인스턴스 자신을 가리키는 참조변수 (즉, 인스턴스의 주소가 저장)

    - 모든 인스턴스 메서드에서 사용 가능하다.

    - 모든 인스턴스 메서드에 지역변수로 "숨겨진 채로 존재" ( main메서드 같은 static메서드에서는 사용 불가)

      -> 숨겨진 채로 존재: 따로 정의하지 않았으나 사용가능하다.

 

  Ex)

<hide/>
package javaStudy;
class Car {
	String color;
	String gearType;
	int door;
	Car(){
		this("white" , "auto" , 4 );
	}
	Car(String color){
		this(color, "auto", 4 );
	}
	Car(String color, String gearType, int door){
		this.color = color;
		this.gearType = gearType;
		this.door = door;
	}
}
public class CarTest2 {
	public static void main(String[] argd) {
	Car c1 = new Car();
	Car c2 = new Car("blue");
	System.out.println("c1의 color = " + c1.color + ", gearType = " + c1.gearType + ", door = " + c1.door );
	System.out.println("c2의 color = " + c2.color + ", gearType = " + c2.gearType + ", door = " + c2.door );
	}
}

  Note) 실행 결과

  - 생성자끼리 호출할 때는 생성자의 이름대신 this를 사용해야하므로 'Car'대신 'this'를 사용한다.  

  - 인스턴스 멤버만 this를 사용할 수 있다. 

 

  5.5 생성자를 이용한 인스턴스의 복사

  - 인스턴스간의 차이는 인스턴스 변수의 값 뿐 나머지는 동일하다.

  - 생성자에서 참조 변수를 매개변수로 받아서 인스턴스 변수들의 값을 복사한다. 

  - 똑같은 속성 값을 갖는 독립적인 인스턴스가 하나 더 만들어진다. 

  Ex) 

<hide/>
package javaStudy;
class Car {
	String color;  // 색상
	String gearType;  // 변속기 종류 - auto(자동), manual(수동)
	int door;  // 문의 개수
	
	Car(){
		this( "White" ,"auto", 4 );
	}
	Car(Car c){  // 인스턴스의 복사를 위한 생성자.
		color = c.color;
		gearType = c.gearType;
		door = c.door;
	}
	Car(String color, String gearType, int door){
		this.color = color;
		this.gearType = gearType;
		this.door = door;
        // this(c.color, c.gearType, c,door);
	}
}
public class CarTest3 {
	public static void main(String[] args) {
		Car c1 = new Car();
		Car c2 = new Car(c1);  // c1의 복사본 c2를 생성한다.
		System.out.println("c1의 color = "+ c1.color + ", gearType = " + c1.gearType + ", door = " + c1.door );
		System.out.println("c2의 color = " + c2.color + ", gearType = " + c2.gearType + ", door = " + c2.door );
		c1.door =  100;  // c1의 인스턴스 변수 door의 값을 변경한다. 
		System.out.println("c1.door = 100; 수행 후");
		System.out.println("c1의 color = "+ c1.color + ", gearType = " + c1.gearType + ", door = " +c1.door );
		System.out.println("c2의 color = " + c2.color + ", gearType = " + c2.gearType + ", door = " + c2.door );
	}
}

  Note) 실행 결과

  - c2는 c1을 복사하여 생성된 것이므로 c1, c2는 서로 같은 상태이지만 서로 독립적으로 메모리 공간에 존재하는 별도의 인스턴스이다.

    -> c1의 값들이 변경되어도 c2는 영향을 받지 않는다.

  - 인스턴스를 생성할 때, 다음의 2가지를 결정해야 한다.

    1) "어떤 클래스"의 인스턴스를 생성할 것인가?

    2) 선택한 클래스의 "어떤 생성자"로 인스턴스를 생성할 것인가?

 

 

6. 변수의 초기화

  6.1 변수의 초기화

  - 변수를 선언하고 처음으로 값을 저장하는 것

  - 쓰레기값을 사용하지 않기 위해 초기화가 필요하다.

  - 멤버변수(인스턴스변수, 클래스변수)와 배열은 각 타입의 기본값으로 자동 초기화 되므로 초기화를 생략할 수 있다. 

  - 지역 변수는 사용전에 꼭! 초기화를 해줘야 한다.

 

  6.2 명시적 초기화(explicit initialization)

  6.3 초기화 블럭(initialization block)

  - 명시적 초기화로 해결되지 않을 때 이용한다.

    1) 클래스 초기화 블럭: 클래스 변수의 복잡한 초기화에 사용된다.

    2) 인스턴스 초기화 블럭: 인스턴스 변수의 복잡한 초기화에 사용된다. 

 

  6.4 멤버변수의 초기화 시기와 순서

  - 클래스 변수 초기화 시점: 클래스가 처음 로딩될 때 단 한 번

    -> 순서: 기본값 -> 명시적 초기화 -> 클래스 초기화 블럭

  - 인스턴스 변수의 초기화 시점: 인스턴스가 생성될 때 마다

    -> 순서: 기본값 -> 명시적 초기화 -> 인스턴스 초기화 블럭 -> 생성자

<hide/>
package javaStudy;
class Product{
	static int count = 0;  // 생성된 인스턴스의 수를 저장하기 위한 변수
	int serialNo;		   // 인스턴스 고유의 번호
	{
		++count;
		serialNo = count;	
	}
	public Product() {}		// 기본 생성자, 생략 가능
}
public class ProductTest {
	public static void main(String[] args) {
	Product p1 = new Product();
	Product p2 = new Product();
	Product p3 = new Product();
	System.out.println("p1의 제품번호(serial no)는 "+ p1.serialNo );
	System.out.println("p2의 제품번호(serial no)는 "+ p2.serialNo );
	System.out.println("p3의 제품번호(serial no)는 "+ p3.serialNo );
	System.out.println("생산된 제품의 수는 모두 "+ Product.count+ "개 입니다." );
	}	
}

  Note) 실행 결과

  - 공장에서 제품을 생산할 때, 제품마다 생산일련번호(serialNo)를 부여하는 것 같이 Product클래스의 인스턴스가 고유의 일련번호를 갖도록 부여함.

  - Product클래스의 인스턴스를 생성할 때마다 인스턴스 블럭이 수행된다. 

  - 클래스 변수count의 값을 1증가시킨 다음, 그 값을 인스턴스 변수 serialNo에 저장한다. 

 

  Def) 인덴테이션: 클래스에 속한 필드나 메서드를 작성할 때, 보통 탭만큼 들여쓴는 방식(가독성을 위해)

 

'Java > Java의 정석' 카테고리의 다른 글

Chapter 08 예외처리 Exception Handling  (0) 2022.02.23
Chapter 07 객체지향 프로그래밍 II  (0) 2022.02.22
Chapter 05 배열(Array)  (0) 2022.02.20
Chapter 04 조건문과 반복문  (0) 2022.02.19
Chapter 03 연산자(Operator)  (0) 2022.02.19