1. 객체 지향 언어
1) 객체 지향 언어의 역사
객체 지향 이론의 기본 개념은 '실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물간의 상호작용이다.'라는 것이다. 실제 사물의 속성과 기능을 분석한 다음, 데이터(변수)와 함수로 정의함으로써 실제 세계를 컴퓨터 속에 옮겨 놓은 것과 같은 가상 세계를 구현하고 이 가상세계에서 모의실험을 함으로써 많은 시간과 비용을 절약할 수 있었다.
2) 객체 지향 언어
객체 지향 언어는 기존 프로그래밍언어에 몇 가지 새로운 규칙을 추가한 보다 발전된 형태의 것이다. 이러한 규칙들을 이용해서 코드 간에 서로 관계를 맺어 줌으로써 보다 유기적으로 프로그램을 구성하는 것이 가능해졌다
객체 지향 언어의 특징
1. 코드의 재사용성이 높다
새로운 코드를 작성할 때 기존의 코드를 이용하여 쉽게 작성할 수 있다
2. 코드의 관리가 용이하다
코드 간의 관계를 이용해서 적은 노력으로 쉽게 코드를 변경할 수 있다
3. 신뢰성이 높은 프로그래밍을 가능하게 한다
제어자와 메서드를 이용해서 데이터를 보호하고 올바른 값을 유지하도록 하며, 코드의 중복을 제거하여 코드의 불일치로 오동작을 방지할 수 있다.
2. 클래스와 객체
1) 클래스와 객체의 정의와 용도
클래스란 '객체를 정의해놓은 것' 또는 '객체의 설계도 또는 틀'이라고 정의할 수 있다.
클래스의 정의 : 클래스란 객체를 정의해 놓은 것이다
클래스의 용도 : 클래스는 객체를 생성하는데 사용된다
객체는 클래스에 정의된 내용대로 메모리에 생성된 것을 뜻한다.
객체 지향 이론에서는 사물과 같은 유형적인 것 뿐만 아니라 개념이나 논리와 같은 무형적인 것들도 객체로 간주한다.
객체의 정의 : 실제로 존재하는 것. 사물 또는 개념
객체의 용도 : 객체가 가지고 있는 기능과 속성에 따라 다름
유형의 객체 : 책상, 의자, 자동차와 같은 사물
무형의 객체 : 수학 공식, 프로그램 에러와 같은 논리나 개념
클래스와 객체의 관계는 제품 설계도와 제품과의 관계라고 할 수 있다. 예를 들면, TV 설계도(클래스)는 TV라는 제품(객체)을 정의한 것이며, TV(객체)를 만드는데 사용된다.
또한 클래스는 단지 객체를 생성하는데 사용될 뿐, 객체 그 자체는 아니다. 우리가 원하는 기능의 객체를 사용하기 위해서는 먼저 클래스로부터 객체를 생성하는 과정이 선행되어야 한다. 그래서 프로그래밍에서는 먼저 클래스를 작성한 다음, 클래스로부터 객체를 생성하여 사용한다.
클래스를 정의하고 클래스를 통해서 객체를 생성하는 이유는 하나의 설계도(클래스)만 제대로 만들어 두면 제품(객체)를 만드는 일이 쉬워지기 때문이다.
JDK에서는 프로그래밍을 위해 많은 수의 유용한 기능(Java API)를 기본적으로 제공하고 있으며, 우리는 이 클래스들을 이용해서 원하는 기능의 프로그램을 보다 쉽게 작성할 수 있다.
2) 객체와 인스턴스
클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화라고 하며, 어떤 클래스로부터 만들어진 객체를 그 클래스의 인스턴스라고 한다.
인스턴스와 객체는 같은 의미지만, 문맥에 따라 구별하여 사용하는 것이 좋다
예를 들어, '책상은 인스턴스이다'보다는 '책상은 객체다'라는 쪽이, '책상은 책상 클래스의 객체이다.'보다는 '책상은 책상 클래스의 인스턴스다'라고 하는 것이 더 자연스럽다
3) 객체의 구성요소 - 속성과 기능
객체는 속성과 기능으로 구성되어 있다. 즉, 객체는 속성과 기능의 집합이라고 할 수 있다,
그리고 객체가 가지고 있는 속성과 기능을 그 객체의 멤버라 한다.
클래스란 객체를 정의한 것이므로 클래스에는 객체의 모든 속성과 기능이 정의되어있다. 클래스로부터 객체를 생성하면, 클래스에 정의된 속성과 기능을 가진 객체가 만들어지는 것이다.
속성과 기능은 아래와 같이 같은 뜻의 여러 가지 용어들이 존재하며, 앞으로 속성보다는 멤버변수를, 기능보다는 메서드를 주로 사용할 것이다.
속성 : 멤버 변수, 특성, 필드, 상태
기능 : 메서드, 함수, 행위
4) 인스턴스의 생성과 사용
TV 클래스를 선언한 것은 TV 설계도를 작성한 것에 불과하므로, TV 인스턴스를 생성해야 제품을 사용할 수 있다. 클래스로부터 인스턴스를 생성하는 방법은 아래와 같다
클래스명 변수명;
변수명 = new 클래스명();
TV t; // TV 클래스 타입의 참조변수 t 선언
t = new TV(); // TV 인스턴스를 생성하고, 생성된 TV 인스턴스의 주소를 t에 저장
- 인스턴스는 오직 참조 변수를 통해서만 다룰 수 있으며, 참조 변수의 타입은 인스턴스 타입과 일치해야 한다
- 같은 클래스로부터 생성되었을지라도 각 인스턴스의 속성은 서로 다른 값을 유지할 수 있으며, 메서드의 내용은 모든 인스턴스에 대해 동일하다
- 참조변수에는 하나의 값만 저장될 수 있으므로 둘 이상의 참조변수가 하나의 인스턴스를 가리키는 것은 가능하지만, 하나의 참조변수로 여러 개의 인스턴스를 가리키는 것은 가능하지 않다.
5) 객체 배열
객체 역시 배열로 다루는 것이 가능하며, 이를 객체 배열이라고 한다. 객체 배열 안에 객체가 저장되는 것은 아니고, 객체의 주소가 저장된다.
객체 배열을 생성하는 것은 그저 객체를 다루기 위한 참조 변수들이 만들어진 것 뿐이지, 아직 객체가 생성되지 않았다. 객체를 생성해서 객체 배열의 각 요소에 저장하는 것을 잊으면 안 된다.
TV[] tvArr = new TV[3]; // 길이가 3인 TV 객체 배열 생성
tvArr[0] = new TV(); // 객체를 생성해 배열의 각 요소에 저장
tvArr[1] = new TV();
tvArr[2] = new TV();
6) 클래스의 또 다른 정의
데이터와 함수의 결합
프로그래밍 언어에서 데이터 처리를 위한 데이터 저장 형태의 발전 과정을 알아보자
1. 변수 : 하나의 데이터를 저장할 수 있는 공간
2. 배열 : 같은 종류의 여러 데이터를 하나의 집합으로 저장할 수 있는 공간
3. 구조체 : 서로 관련된 여러 데이터를 종류에 관계없이 하나의 집합으로 저장할 수 있는 공간
4. 클래스 : 데이터와 함수의 결합 (구조체 + 함수)
자바와 같은 객체 지향 언어에서는 변수(데이터)와 함수를 하나의 클래스에 정의하여 서로 관계가 깊은 변수와 함수들을 다룰 수 있게 했다
사용자 정의 타입
자바와 같은 객체 지향 언어에서는 클래스가 곧 사용자 정의 타입이다. 기본형의 개수는 8개로 정해져 있지만, 참조형의 개수가 정해져 있지 않은 이유는 프로그래머가 새로운 타입을 추가할 수 있기 때문이다.
아래 코드는 시, 분, 초를 저장하기 위한 세 변수를 멤버 변수로 갖는 Time 클래스를 정의한 것이다.
class Time{
int hour;
int minute;
float second;
}
3. 변수와 메서드
1) 선언 위치에 따른 변수의 종류
변수는 클래스 변수, 인스턴스 변수, 지역 변수 모두 세 가지가 있다. 변수의 종류를 결정짓는 중요한 요소는 '변수의 선언된 위치'이므로 변수의 종류를 파악하기 위해서는 변수가 어느 영역에 선언되었는지를 확인하는 것이 중요하다
변수의 종류 | 선언 위치 | 생성 시기 |
클래스 변수 | 클래스 영역 | 클래스가 메모리에 올라갈 때 |
인스턴스 변수 | 인스턴스가 생성되었을 때 | |
지역 변수 | 클래스 영역 이외의 영역 (메서드, 생성자, 초기화 블럭 내부) |
변수 선언문이 수행되었을 때 |
class Hello {
int a = 10; // 인스턴스 변수
static int b = 100; // 클래스 변수
void method() {
int c = 1000; // 지역 변수
}
}
- 인스턴스 변수
- 클래스 영역에 선언
- 클래스의 인스턴스를 생성할 때 만들어짐 (인스턴스 생성 후 인스턴스 변수 사용 가능)
- 인스턴스마다 고유한 상태를 유지해야하는 속성의 경우, 인스턴스 변수로 선언 - 클래스 변수
- 인스턴스 변수 앞에 static을 붙이면 됨
- 모든 인스턴스가 공통된 저장공간(변수)를 공유하게 됨 (즉, 모든 인스턴스들이 공통적인 값을 사용)
- 전역 변수의 성격을 가짐
- 갹채 생성 없이 '클래스이름.클래스변수'로 직접 사용 가능
- 하나의 인스턴스에서 클래스 변수의 값을 바꾸면 모든 인스턴스에서 해당 클래스 변수의 값이 바뀐다 - 지역 변수
- 메서드 내에 선언되며 메서드 내에서만 사용 가능함
- 메서드가 종료되면 소멸되어 더 이상 사용 불가
2) 클래스 변수와 인스턴스 변수
카드를 예를 들어 보자. 카드는 폭, 높이, 각 카드 만의 무늬와 숫자가 존재한다.
이 때 모든 카드들이 동일해야 하는 폭과 높이는 클래스 변수로, 각 카드들이 서로 달라야 하는 무늬와 숫자는 인스턴스 변수로 선언하는 것이 맞다. 이것이 클래스 변수와 인스턴스 변수의 차이이다.
클래스 변수를 사용할 때는 Card.width와 같이 '클래스이름.클래스변수'의 형태로 사용하는 것이 좋다. 참조 변수 c1, c2를 통해서 클래스 변수를 사용하면 클래스 변수를 인스턴스 변수로 오해할 수 있기 때문이다
인스턴스 변수는 인스턴스가 생성될 때 마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스가 하나의 저장 공간을 공유하므로, 항상 공통된 값을 갖는다.
3) 메서드
메서드는 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것이다.
기본적으로 수학의 함수와 유사하며, 어떤 값을 입력하면 이 값으로 작업을 수행해서 결과를 반환한다.
메서드를 사용하는 이유
1. 높은 재사용성
한번 만들어 놓은 메서드는 몇 번이고 호출할 수 있으며, 다른 프로그램에서도 사용이 가능하다
2 중복된 코드의 제거
프로그램을 작성하다보면, 같은 내용의 문장들이 여러 곳에 반복해서 나타나게 된다. 이처럼 반복적으로 나타나는 문장들을 메서드로 만들어서 사용하면 코드의 중복이 제거되고, 변경 사항이 발생했을 때 이 메서드만 수정하면 되므로 관리도 쉽고 오류의 발생 가능성도 낮아진다
3. 프로그램의 구조화
큰 규모의 프로그램에서는 문장들을 작업 단위로 나누어서 여러 개의 메서드에 담아 프로그램의 구조를 단순화시키는 것이 필수적이다
4) 메서드의 선언과 구현
메서드를 정의한다는 것은 선언부와 구현부를 작성하는 것을 뜻한다.
반환타입 메서드이름 (타입변수명1, 타입변수명2, ... ) {
// 메서드 호출 시 수행될 코드
}
메서드 선언부
메서드 선언부는 '메서드의 이름', '매개변수 선언', '반환타입'으로 이루어져 있다. 메서드가 작업을 수행하기 위해 어떤 값들을 필요로 하고 작업의 결과로 어떤 타입의 값을 반환하는지에 대한 정보를 제공한다
1. 매개 변수 선언
매개 변수는 메서드가 작업을 수행하는데 필요한 값들을 제공받기 위한 것이다
2. 메서드 이름
메서드는 특정 작업을 수행하므로 메서드의 이름은 동사인 경우가 많다. 이름만으로도 메서드의 기능을 쉽게 알 수 있도록 함축적이면서도 의미있는 이름을 짓도록 노력해야 한다
3. 반환 타입
메서드의 작업 수행 결과의 반환값의 타입을 적는다. 반환값이 없는 경우 반환타입으로 void를 적어야 한다.
메서드 구현부
메서드의 선언부 다음에 오는 괄호 {}를 '메서드의 구현부'라고 하는데, 여기에 메서드를 호출했을 때 수행될 문장들을 넣는다
.1. return 문
메서드의 반환 타입이 void가 아닌 경우, 구현부 안에 'return 반환값;'이 반드시 포함되어야 한다. 이 문장은 작업을 수행한 결과인 반환값을 호출한 메서드로 전달하는데, 이 값의 타입은 반환타입과 일치하거나 적어도 자동 형변환이 가능한 것이어야 한다
2. 지역 변수
메서드 내에 선언된 변수들은 그 메서드 내에서만 사용할 수 있으므로 서로 다른 메서드라면 같은 이름의 변수를 선언해도 된다.
5) 메서드의 호출
메서드를 정의하였어도 호출하지 않으면 아무 일도 발생하지 않는다.
- 인자(argument) : 메서드를 호출할 때 괄호() 안에 지정한 값
- 매개변수(parameter) : 메서드를 선언할 때 괄호 안에 작성한 변수들
int result = add(3,5); // 3과 5는 인자
int add(int x, int y){ // x와 y는 매개변수
return x+y;
}
6) return 문
return 문은 현재 실행중인 메서드를 종료하고 호출한 메서드로 되돌아 간다. 반환값의 유무와 관계없이 모든 메서드에는 적어도 하나의 return 문이 존재해야 한다. 반환 타입이 void인 경우에는 컴파일러가 자동적으로 'return ;'을 추가해주기에 아무런 문제가 없지만, 반환 타입이 void가 아닌 경우에는 반드시 return 문을 작성해야 한다
7) JVM의 메모리 구조
JVM은 Java Virtual Machine의 줄임말로, OS에 종속받지 않고 CPU가 JAVA를 인식, 실행할 수 있게 하는 가상 컴퓨터라는 뜻이다. 응용 프로그램이 실행되면 JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고 JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.
메서드 영역
클래스에 대한 정보(클래스 데이터)가 이곳에 저장된다. 이 때, 그 클래스의 클래스 변수도 이 영역에 함께 생성된다
힙
인스턴스가 생성되는 공간, 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 생성된다. 즉, 인스턴스 변수들이 생성되는 공간이다.
호출 스택
메서드의 작업에 필요한 메모리 공간을 제공한다. 메서드가 호출되면, 호출 스택에 호출된 메서드를 위한 메모리가 할당되며, 이 메모리는 메서드가 작업을 수행하는 동안 지역 변수들과 연산의 중간 결과 등을 저장하는데 사용된다. 그리고 메서드가 작업을 마치면 할당되었던 메모리 공간은 반환되어 비워진다.
호출 스택을 조사해보면 메서드 간의 호출관계와 현재 수행중인 메서드가 어느 것인지 알 수 있다
- 메서드가 호출되면 수행에 필요한 만큼의 메모리를 스택에 할당받는다
- 메서드가 수행을 마치고나면 사용했던 메모리를 반환하고 스택에서 제거된다
- 호출 스택의 제일 위에 있는 메서드가 현재 실행 중인 메서드이다
- 아래에 있는 메서드가 바로 위의 메서드를 호출한 메서드이다.
8) 기본형 매개변수와 참조형 매개변수
메서드의 매개변수를 기본형으로 선언하면 단순히 저장된 값만 얻지만, 참조형으로 선언하면 값이 저장된 곳의 주소를 알 수 있기 때문에 값을 읽어 오는 것은 물론 값을 변경하는 것도 가능하다
기본형 매개변수 : 변수의 값을 읽기만 할 수 있다 (read only)
참조형 매개변수 : 변수의 값을 읽고 변경할 수 있다 (read & write)
9) 참조형 반환타입
매개변수 뿐만 아니라 반환타입도 참조형이 될 수 있다. 반환타입이 참조형이라는 것은 반환하는 값의 타입이 참조형이라는 얘기인데, 모든 참조형 타입의 값은 '객체의 주소'이므로 그저 정수값이 반환되는 것일 뿐 특별할 것이 없다.
10) 재귀 호출
메서드의 내부에서 메서드 자신을 다시 호출하는 것을 '재귀 호출'이라 하고, 재귀 호출을 하는 메서드를 '재귀 메서드'라고 한다. 재귀 호출만 하는 코드만 있다면 무한루프에 빠지게 되므로 재귀 호출에는 조건문이 필수적이다.
재귀 호출은 반복문과 유사한 점이 많으며, 대부분의 재귀호출은 반복문으로 작성하는 것이 가능하다. 그럼에도 재귀 호출을 사용하는 이유는 재귀 호출이 주는 논리적 간결함 때문이다. 몇 겹의 반복문과 조건문으로 복잡하게 작성된 코드가 재귀 호출로 작성하면보다 단순한 구조로 바뀔 수도 있다. 하지만 재귀 호출은 비효율적이므로 재귀 호출에 드는 비용보다 재귀 호출의 간결함이 주는 이득이 충분히 큰 경우에만 사용해야 한다는 점을 기억하자
11) 클래스 메서드(static 메서드)와 인스턴스 메서드
변수에서 그랬던 것과 같이, 메서드 앞에 static이 붙어 있으면 클래스 메서드이고 붙어 있지 않으면 인스턴스 메서드이다.
- 인스턴스 메서드 : 인스턴수 변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드
- 클래스 메서드 : 인스턴스와 관계 없는 메서드
1. 클래스를 설계할 때, 멤버 변수(클래스 변수, 인스턴스 변수) 중 모든 인스턴스에 공통적으로 사용하는 것에 static을 붙인다.
생성된 각 인스턴스는 서로 독립적이기 때문에 각 인스턴스의 변수는 서로 다른 값을 유지한다. 그러나 모든 인스턴스에서 같은 값이 유지되어야 하는 변수는 static을 붙여서 클래스 변수로 정의해야 한다
2. 클래스 변수(static 변수)는 인스턴스를 생성하지 않아도 사용할 수 있다.
static이 붙은 변수는 클래스가 메모리에 올라갈 때 이미 자동적으로 생성되기 때문이다
3. 클래스 메서드는 인스턴스 변수를 사용할 수 없다
인스턴스 변수는 인스턴스가 반드시 존재해야만 사용할 수 있는데, 클래스 메서드는 인스턴스 생성 없이 호출 가능하므로 클래스 메서드가 호출되었을 때 인스턴스가 존재하지 않을 수도 있다. 그래서 클래스 메서드에서 인스턴스 변수의 사용을 금지한다.
4. 메서드 내에서 인스턴스 변수를 사용하지 않는다면 static을 붙이는 것을 고려한다
인스턴스 변수를 필요로 하지 않는다면 static을 붙이자. 메서드 호출 시간이 짧아지므로 성능이 향상된다. static을 안 붙인 메서드는 실행 시 호출되어야 할 메서드를 찾는 과정이 추가적으로 필요하기 때문에 시간이 더 걸린다.
12) 클래스 멤버와 인스턴스 멤버 간의 참조와 호출
같은 클래스에 속한 멤버들 간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출이 가능하다. 단, 클래스 멤버가 인스턴스 멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다. 그 이유는 인스턴스 멤버가 존재하는 시점에 클래스 멤버는 항상 존재하지만, 클래스 멤버가 존재하는 시점에 인스턴스 멤버가 존재하지 않을 수도 있기 때문이다.
4. 오버로딩(overloading)
1) 오버로딩이란?
자바에서는 한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메서드가 있더라도 매개변수의 개수 또는 타입이 다르면, 같은 이름을 사용해서 메서드를 정의할 수 있다. 이처럼, 한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것을 오버로딩이라고 한다. 오버로딩의 사전적 의미는 과적하다 즉, 많이 싣는 것을 뜻한다. 보통 하나의 메서드 이름에 하나의 기능만 구현해야 하는데, 하나의 메서드 이름으로 여러 기능을 구현하기 때문에 붙여진 이름이다.
2) 오버로딩의 조건
오버로딩은 메서드의 이름이 같다 하더라도 매개변수가 다르면 서로 구별될 수 있기 때문에 오버로딩이 가능한 것이다.
1. 메서드 이름이 같아야 한다
2. 매개변수의 개수 또는 타입이 달라야 한다
5. 생성자(Constructor)
1) 생성자란?
생성자는 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'이다. 따라서 인스턴스 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용된다.
- 생성자는 메서드처럼 클래스 내에 선언되며, 구조도 메서드와 유사하지만 리턴값이 존재하지 않는다
- 생성자의 이름은 클래스의 이름과 같아야 한다
- 생성자도 오버로딩이 가능하므로 하나의 클래스에 여러 개의 생성자가 존재할 수 있다.
Class Card{
Card(){ // 매개변수가 없는 생성자
}
Card(int num, String k){ // 매개변수가 있는 생성자
}
}
지금까지 인스턴스를 생성하기 위해 사용해왔던 '클래스이름()'이 바로 생성자였던 것이다. 인스턴스를 생성할 때는 반드시 클래스 내에 정의된 생성자 중의 하나를 선택하여 지정해주어야 한다
Card c = new Card();
1. 연산자 new에 의해서 메모리(heap)에 Card 클래스의 인스턴스가 생성된다.
2. 생성자 Card()가 호출되어 수행된다
3. 연산자 new의 결과로, 생성된 Card 인스턴스의 주소가 반환되어 참조변수 c에 저장된다.
2) 기본 생성자 (default constructor)
컴파일 할 때, 소스 파일의 클래스에 생성자가 하나도 정의되지 않은 경우 컴파일러는 자동적으로 '클래스이름()' 와 같은 내용의 기본 생성자를 추가하여 컴파일 한다. 컴파일러가 자동으로 추가해주는 기본 생성자는 매개변수도 없고 아무런 내용도 없는 아주 간단한 것이다.
기본 생성자가 컴파일러에 의해서 추가되는 경우는 클래스에 정의된 생성자가 하나도 없을 때 뿐이다. 즉, 클래스 안에 다른 생성자가 하나라도 존재하는 경우 기본 생성자는 추가 되지 않는다.
3) 매개변수가 있는 생성자
인스턴스마다 각기 다른 값으로 초기화되어야 하는 경우가 많기 때문에 매개변수를 사용한 초기화는 매우 유용하다. 매개 변수가 있는 생성자를 사용하면 인스턴스를 생성하는 동시에 원하는 값으로 초기화를 할 수 있게 된다.
4) 생성자에서 다른 생성자 호출하기 - this(), this
같은 클래스의 멤버들 간에 서로 호출할 수 있는 것처럼 생성자 간에도 서로 호출이 가능하다. 단, 다음의 두 조건을 만족시켜야 한다
- 생성자의 이름으로 클래스 이름 대신 this를 사용한다
- 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다
생성자에서 다른 생성자를 첫줄에서만 호출이 가능하도록 한 이유는 생성자 내에서 초기화 작업 도중에 다른 생성자를 호출하게 되면, 호출된 다른 생성자 내에서도 멤버 변수들의 값을 초기화할 것이므로 다른 생성자를 호출하기 이전의 초기화 작업이 무의미해질 수 있기 때문이다.
class Car{
String color;
String gearType;
Car(){
this("white", "auto");
}
Car(String color){
this(color, "auto");
}
Car(String color, String gearType){
this.color = color;
this.gearType = gearType;
}
}
this : 인스턴스 자신을 가리키는 참조변수. 인스턴스의 주소가 저장되어 있다.
모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재한다
this(), this(매개변수) : 생성자. 같은 클래스의 다른 생성자를 호출할 때 사용한다
6. 변수의 초기화
1) 변수의 초기화
변수를 선언하고 처음으로 값을 저장하는 것을 변수의 초기화라고 한다. 멤버 변수는 초기화하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지므로 초기화하지 않고 사용해도 되지만, 지역 변수는 사용하기 전에 반드시 초기화해야 한다
멤버 변수의 초기화 방법
1. 명시적 초기화
2. 생성자
3. 초기화 블럭
- 인스턴스 초기화 블럭 : 인스턴스 변수를 초기화하는데 사용
- 클래스 초기화 블럭 : 클래스 변수를 초기화하는데 사용
2) 명시적 초기화 (explicit initialization)
변수를 선언과 동시에 초기화하는 것을 명시적 초기화라고 한다. 가장 기본적이면서도 간단한 초기화 방법이므로 여러 초기화 방법 중에서 가장 우선적으로 고려되어야 한다
class Car{
int door = 4; // 기본형 변수의 초기화
Engine e = new Engine(); // 참조형 변수의 초기화
}
3) 초기화 블럭
초기화 블럭에는 클래스 초기화 블럭과 인스턴스 초기화 블럭 두 가지가 존재한다
클래스 초기화 블럭 : 클래스 변수의 복잡한 초기화에 사용된다
인스턴스 초기화 블럭 : 인스턴스 변수의 복잡한 초기화에 사용된다
class InitBlock{
static {
// 클래스 초기화 블럭
}
{
// 인스턴스 초기화 블럭
}
}
클래스 초기화 블럭은 클래스가 메모리에 처음 로딩될 때 한번만 수해되며, 인스턴스 초기화 블럭은 생성자와 같이 인스턴스를 생성할 때마다 수행된다. 그리고 생성자보다 인스턴스 초기화 블럭이 먼저 수행된다.
4) 멤버 변수의 초기화 시기와 순서
클래스 변수의 초기화 시점 : 클래스가 처음 로딩될 때 단 한 번 초기화 된다
인스턴스 변수의 초기화 시점 : 인스턴스가 생성될 때마다 각 인스턴스별로 초기화가 이루어진다
클래스 변수의 초기화 순서 : 기본값 -> 명시적 초기화 -> 클래스 초기화 블럭
인스턴스 변수의 초기화 순서 : 기본값 -> 명시적 초기화 -> 인스턴스 초기화 블럭 -> 생성자
'백엔드 > JAVA' 카테고리의 다른 글
[JAVA의 정석] Ch 8. 예외 처리 (0) | 2025.04.07 |
---|---|
[JAVA의 정석] Ch 7. 객체 지향 프로그래밍 2 (0) | 2025.04.05 |
[JAVA의 정석] Ch 5. 배열 (0) | 2025.03.19 |
[JAVA의 정석] Ch 3. 연산자(operator) (0) | 2025.03.11 |
[JAVA의 정석] Ch 2. 변수(Variable) (0) | 2025.03.01 |