🏃♂️ 들어가기 앞서..
본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕
*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.
이번에는 저번 정리(객체 지향 프로그래밍 Ⅰ 정리 - (2))에 이어서
생성자와 초기화에 대해 자세히 알아보도록 하자.
constructor
인스턴스가 생성될 때 호출되는
" 인스턴스 초기화 (인스턴스 변수 초기화) 메서드 "
이름 때문에
인스턴스를 생성하나...? 라는 오해가 생길 수 있는데
( 진짜 생성은 연산자 new
를 통해 하는 것이지
생성자가 하는게 아니라는 것을 명심해야 한다. )
주로 " 인스턴스 변수 초기화 " 작업에 사용된다.
(인스턴스 생성 시에 실행되야하는 작업을 위해서도 사용됨.)
선언하는 방법이나 구조가
메서드와 상당히 유사하다.
우선,
생성자는
클래스 내에 선언되고
구조는 비슷하나 return값이 없다는 특징이 있다.
(단, return값이 없다고 메서드처럼 앞에 void를 붙이지 않는다.)
정의하는 방법은
다음과 같다.
오버로딩도 가능하기때문에
" 한 클래스에 여러 생성자 가 존재할 수 있다. "
// 정말 메서드와 유사하다.
클래스 이름 (Type 변수명, Type 변수명,...) {
/*
인스턴스 생성 시 수행될 코드
(주로 인스턴스 초기화 코드 작성)
*/
}
default
)사실 클래스에 " 생성자를 정의하지 않고도 "
인스턴스를 생성할 수 있었던 이유는
컴파일러가 제공하는 이 기본 생성자를 자동으로 추가하여 컴파일하기 때문이다.
( 소스파일*.java
의 클래스에 생성자가 정의되지 않으면 자동적으로 아래와 같은 기본 생성자를 추가함. )
클래스 이름() { }
Point() { }
보이는 것처럼
이 자동 추가된 기본 생성자는
매개변수 없고, 아무런 내용 없는 간단한 생성자이다.
단,
" 클래스 내에 별도의 생성자가 정의되어 있는 상태 "라면
컴파일 에러가 발생한다.
class Data_1 {
int value;
}
class Data_2 {
int value;
// 인스턴스를 만들기 위해선 int x 매개변수에 인수 투입이 필요함
Data_2(int x) { // 매개변수가 있는 별도의 생성자
value = x;
}
}
class Test {
public static void main(String[] args) {
Data_1 d1 = new Data_1();
Data_2 d2 = new Data_2(); // 별도의 생성자가 있는 클래스 -> Compile Error
}
}
Data_1 d1 = new Data_1();
Data_2 d2 = new Data_2(); // 에러
// 에러 발생 해결
Data_2 d2 = new Data_2(10); // 매개변수에 들어갈 값 투입 -> Error X
파이썬에 비교한다면
파이썬의 __init__
의 역할과 동일하다 생각하면 쉽다.
위에서 살펴봤듯
객체를 시작을 만들기 위해
즉, 초기화를 하기 위해 매개변수를 입력해야 하는 생성자라고 보면 된다.
사용자의 설계에 따라
간결하고 간편하게 인스턴스를 만들 수 있게끔 도와준다.
예를 들면
class Car {
String color;
String company;
int door;
Car() {} // 클래스 내 기본 생성자
// 인수가 투입되었을 때, 인스턴스가 어떻게 생성되는지 미리 설계해놓는 것
Car(String col, String comp, int d) {
color = col;
company = comp;
door = d;
}
}
// 기본 생성자 사용
Car c = new Car();
c.color = "white" ;
c.company = "Audi" ;
c.door = 2;
// 매개변수 있는 생성자 사용
Car c = new Car("white", "Audi", 2) ;
this()
" 와 "this
"this()
같은 클래스의 멤버들 간에 서로 다른 생성자를 호출할 때 사용
※ 조건
- 생성자 이름 : this (클래스 이름 X)
- 다른 생성자 호출할 땐, 반드시 첫 줄에서만 호출 가능
( 생성자 내에서 초기화 도중 다른 생성자를 호출하게 되면
다른 생성자 내의 멤버변수들 값도 초기화 할 것이기 때문에 이전의 초기화 작업이 무의미해질 수가 있음 )
기본 값을 정하고
인스턴스를 생성할 때,
매개변수에 들어올 값들의 경우의 수에 대해 고려한다고 하면 이해하기 편할 것이다.
예시를 통해 살펴보자.
class Car2 {
String color;
String company;
int door;
Car2(){
this("white", "Audi", 2);
}
/*
동일하게 초기화
Car2(){
color = "white";
company = "Audi";
door = 2;
}
*/
Car2(String color){
this(color, "Audi", 2);
}
// 이 경우는 this() 호출의 경우가 아님 _ 주의!!
Car2(String color, String company, int door){
this.color = color ;
this.company = company ;
this.door = door ;
}
}
//기본 생성
Car2 c1 = new Car2();
//color만 따로 별도 입력
Car2 c1 = new Car2("red");
//모든 변수 별도 입력
Car2 c1 = new Car2("blue", "Benz", 4);
이렇게 같은 클래스 내의
생성자들을 서로 호출하도록 유기적으로 연결해주면
여러 옵션(경우의 수)에 대비할 수 있고
수정이 필요한 경우 효율적으로 적은 코드 변경 해결이 가능하다.
this
자기 자신을 가르키는 참조 변수로
" 인스턴스 변수 "와 " 지역 변수/매개변수 "간의 구별에 용이하다.
(this는 인스턴스 멤버만 사용 가능하다.)
예시를 보면서 이해하는 것이 좋을 것 같다.
//이 경우에는 구별에 문제가 없다.
// 매개변수(Local Variable) : "col" / 인스턴스 변수(Instance Variable) : "c"
Car(String col, String comp, int d) {
color = col;
company = comp;
door = d;
}
// 하지만 두 변수의 이름이 같다면 구별 불가
// 매개변수(Local Variable) : "color" / 인스턴스 변수(Instance Variable) : "color"
Car(String color, String company, int door) {
//color = color;
this.color = color; // 구분 가능
//company = company;
this.company = company; // 구분 가능
//door = door;
this.door = door; // 구분 가능
}
앞서 this는 인스턴스 멤버만 사용 가능하다고 설명을 해놨는데
그 이유는
static메서드(클래스메서드)에서 인스턴스 멤버들을 사용할 수 없는 이유와 동일하다.
클래스 메서드는
인스턴스 생성 없이도 호출이 가능하기 때문에
static메서드가 호출되는 상황에
" 인스턴스가 존재하지 않을 수도 있기 " 때문이다.
* 가능하면 선언과 동시에 적절한 값으로 초기화 하는 것이 바람직하다.
- 멤버변수[ : 클래스변수 & 인스턴스 변수 ] or 배열 : 선택적 초기화
- ★ 지역변수 : 필수적 초기화
📌 각 타입 기본값
자료형 기본값 boolean
false
char
'\u0000'
byte
,short
,int
0
long
0L
float
0.0f
double
0.0d
or0.0
참조형 null
class InItTest {
int x ; // 인스턴스 변수 : 명시적으로 지정해주지 않아도 기본값 "0"이 들어감
int y = x ; // 인스턴스 변수 : x에 자동으로 기본값으로 초기화되었기 때문에 0이라는 값이 유효 -> y도 0
void method1() {
int i ; // 지역변수 : 초기화가 자동으로 되지않음.
int k = i ; // 지역변수 : i가 초기화 되지도 않았는데 무슨... 불가능! -> 에러Error
}
}
위 예시처럼
인스턴스 변수인 x
는 기본값 0으로 자동 초기화가 되기때문에 에러가 발생하지 않지만
void method1()
의 지역 변수 i
는 자동 초기화가 되지 않기 때문에
컴파일 시, 에러가 발생한다.
앞서 알아봤던 것처럼
지역변수와 달리 멤버변수는 각 타입의 기본값으로 자동 초기화가 된다고 했는데
전체적인 " 초기화되는 순서 "를 살펴보면
explicit initialization
)" 선언과 동시에 초기화하는 것 "
initialization block
)초기화 블럭은 두 가지의 종류가 있는데
클래스와 인스턴스로 나뉜다.
이 초기화 블럭을 작성하는 방법은
기억하기 쉽다.
우선 < 인스턴스 초기화 블럭 >은
단순히 클래스 내에 블럭{}
을 만들고
그 안에 코드를 작성하는 것이고
< 클래스 초기화 블럭 >은
이 인스턴스 초기화 블럭 앞에 static을 붙이면 된다.
물론 초기화 순서를 보면 알겠지만
가장 먼저 수행되는 것은 " 클래스 초기화 블럭 내 작성한 코드 "이고
그 다음으로 인스턴스 초기화 블럭, 그리고 생성자 순으로 수행된다.
순서는 위와 같은 순서이고
수행되는 경우는
클래스 초기화 블럭의 경우 처음 메모리에 로딩될 때 한 번만 수행되지만
인스턴스 초기화 블럭의 경우 인스턴스 생성 때마다 수행된다.