관리 메뉴

나구리의 개발공부기록

자바의 정석 기초편 ch6 - 32 ~ 41[생성자, 기본 생성자,생성자this(), 참조변수 this, 변수의초기화, 멤버변수의 초기화] 본문

유튜브 공부/JAVA의 정석 기초편(유튜브)

자바의 정석 기초편 ch6 - 32 ~ 41[생성자, 기본 생성자,생성자this(), 참조변수 this, 변수의초기화, 멤버변수의 초기화]

소소한나구리 2023. 11. 20. 16:34

1) 생성자

  • 인스턴스가 생성될 때마다 호출되는 인스턴스 초기화 메서드 = 객체(iv묶음) 초기화 메서드
  • 인스턴스 생성 시 수행할 작업(iv초기화)에 사용
// 1. 객체생성
Time t = new Time();	// Time() : 기본 생성자 호출

// 2. iv초기화
t.hour = 12;
t.minute = 34;
t.second = 56;

// 위 1,2번을 한번에(생성자에 매개변수를 입력)
Time t = new Time(12,34,56);	// 객체생성과 iv초기화를 한번에
Time(12,34,56); 매개변수가 있는 생성자 호출
  • 생성자의 이름은 클래스와 이름과 같아야 함
클래스이름(타입 변수명, 타입 변수명, ...) {
	// 인스턴스 생성 시 수행될 코드,
	// 주로 인스턴스 변수의 초기화 코드를 작성
}
  • 리턴값이 없음(void 안붙임)
  • 모든 클래스는 반드시 1개 이상의 생성자가 있어야 함.
  • 여태까지 예제를 보면 생성자가 없이 동작했는데 그 이유는 기본생성자는 컴파일러가 자동으로 만들어주기 때문임 -> 아래에 기본생성자 내용 참조
class Card {	// 클래스 이름
	// ... 기타 코드들
    
    card () {	//	 매개변수가 없는 기본생성자 오버로딩
    
    // ... 인스턴스 초기화 작업
    
    }
    
    card(String kind, int number) { // 생성자 오버로딩(매개변수가 있는 생성자)
    
    // ... 인스턴스 초기화 작업
    
    }
}
// 항상 반환값이 없기 때문에 void가 생략됨(규칙)

2) 기본생성자

  • 매개 변수가 없는 생성자
  • 생성자가 하나도 없을 때만 컴파일러가 자동으로 추가해줌
  • 그러나 원래는 직접 만들어 주는 것이 원칙임
  • 아래 예제를 보면 Data_2() 객체를 생성할 때 컴파일 에러가 나는데 매개변수가 있는 생성자를 생성하면 컴파일러가 자동으로 기본생성자를 만들어 주지 않기 때문임
  • 코드 작성 시 직접 기본 생성자를 입력해주는 습관이 필요함
class Data_1 {	// 생성자가 하나도 없음
	int value;
//	Data_1(){}	// 기본생성자가 자동으로 추가 됨
}

// 매개변수가 있는 생성자를 생성하고 기본생성자를 직접 만들어주지 않으면 컴파일 에러가 발생함
// 기본생성자를 꼭 작성 해주는 습관이 필요 함
class Data_2 {
	int value;
	
// 	Data_2() {}	// 기본생성자를 생성하면 complie 에러가 없어짐

	Data_2(int x) {   // 매개변수가 있는 생성자.
		value = x;
	}
}

 class ex6_11 {
	public static void main(String[] args) {
		Data_1 d1 = new Data_1();
		Data_2 d2 = new Data_2(); // compile error발생
//		The constructor Data_2() is undefined (Data_2가 없다 = 기본생성자가 없다)
		
	}
}

3) 매개변수가 있는 생성자

  • 대부분 생성자를 사용할 때는 변수를 초기화해야하기 때문에 매개 변수가 있음
  • 생성자 호출 시 매개변수를 입력하여 초기화를 간단히 할 수 있어 코드가 간결해짐
  • 객체를 생성할일이 많아지면 많아질 수록 값을 초기화하는 코드들이 사라지게되어 편의성이 더욱 증가하게 됨
class Car {
	String color;	//색상
	String gearType;	// 변속기 종류 = auto(자동), manual(수동)	
	int door;	//문의개수
	
	Car() {}	// 기본생성자
	Car(String c, String g, int d) {	// 매개변수가 있는 생성자
		color = c;	// iv
		gearType = g;	// iv
		door = d;	// iv
    }
}

// 객체 생성 
Car c = new Car();
// iv 초기화
c.color = "white";
c.gearType = "auto";
c.door = 4;

// 위 코드를 한방에
Car c = new Car("white", "auto", 4);
// 1.참조변수 생성
// 2.new = 객체생성
// 3.Car("white", "auto", 4) = 객체 초기화, 생성자 호출
// 4.객체의 주소가 c에 저장

4) 생성자 this()

  • 같은 클래스내의 생성자를 호출하기위해 사용
  • 반드시 첫줄에서만 사용가능하며 다른 줄에서 호출 시 에러
  • 생성자 오버로딩을 활용하여 코드 중복을 제거하기 위해 주로 활용 됨
class Car2{
	String color;
	String gearType;
	int door;
	
    // 매개변수가 없는 생성자를 호출 시 지정된 값이 초기화 되도록 디폴트 값 설정하려고 하면 코드 중복이 발생
//	Car2() { 
//		color = "white";
//		gearType = "auto";
//		door = 4;
//	}
	
	// this를 사용하여 코드 중복을 제거(코드 중복을 제거하는 것이 좋은 코드임)
	Car2() {
		this ("white","auto",4);
	}
	
    // 이렇게 생성자 오버로딩 시 this()가 자주 활용 됨
	Car2(String c, String g) {
		this (c, g, 5);	// 
	}
    
    // 매개변수가 3개인 생성자
	Car2(String c, String g, int d) {
		color = c;
		gearType = g;
		door = d;
	}
    

}

5) 참조변수 this

  • this()와는 전혀 다른 기능을 함
  • 인스턴스 자신을 가리키는 참조변수이며 인스턴스 메서드(생성자 포함)에서만 사용가능
  • 지역변수(lv)와 인스턴스 변수(iv)를 구별할 때 사용하며 같은 클래스 내에서는 this를 생략할 수 있음
  • this.변수이름
// color,gearType,door = iv
// (String c, String g, int d) 와 c,g,d 모두 lv
Car(String c, String g, int d){
	
    // 원래는 this.을 붙여야 하지만 같은 클래스 안에 쓰일 경우에는 생략 가능함
    color = c;		// this.color
    gearType = g;	// this.gearType
    door = d;		// this.door
   
}

// 아래처럼 iv와 lv와 이름이 같을 경우 구분을 위해 this.를 붙임
// 생성자로 iv를 초기화 시 아래처럼 명확히 구분하기 위해 this를 사용하는 쪽이 더 많이 사용됨
Car(String color, String gearType, int door) {
	this.color = color;
	this.gearType = gearType;
	this.door  = door;
}

 

(1) this.

  • 인스턴스 자신을 가리키는 참조변수
  • this에는 인스턴스의 주소가 저장되어 있음
  • 모든 인스턴스메서드에 지역변수로 숨겨져 존재하여 this를 선언하지 않아도 iv를 사용할 수 있음

(2) this()

  • this(매개변수)는 해당 클래스의 생성자를 호출하는 것
  • 같은 클래스의 여러 생성자를 호출할 때 클래스의 이름 대신해서 사용
class MyMath2 {
	long a, b;	// 원래는 this.a, this.b / 생략가능
    
    MyMath2(int a, int b) {	// 생성자
    	// this 생략불가 -> iv와 lv가 이름이 같아서 lv로 간주 됨
        this.a = a;	// lv와 iv를 구분하기위해 this를 붙임
        this.b = b;	// 위와 동일
    }
    long add() { //인스턴스 메서드
    	return a + b; // 원래는 return this.a + this.b; / 생략가능
    }
    
    static long add(long a, long b) {	// 클래스 메서드(static메서드)
    	return a + b; 	// lv
        // iv 사용불가 = this 사용불가 (this가 객체)
    }
// 생성자와 인스턴스 메서드에서만 this 사용가능
// 클래스 메서드에서는 객체를 사용 못하므로 this 사용 불가

6) 변수의 초기화

  • 멤버변수(iv, cv)는 자동으로 기본값이 초기화 됨
  • 객체는 여러 변수를 묶어 놓은 것인데 매번 직접 초기화를 하게되면 코드작성이 너무 많아져 편의를 위해 자동 초기화 됨(배열도 동일)
  • 그러나 지역변수(lv)는 사용전에 꼭 수동 초기화(사용자가 직접 초기화) 해야함, 자동 초기화가 안됨
class initTest {
	int x;		// iv
	int y = x;	// iv OK = 기본값으로 자동 초기화 됨
    
	void method1() {
    	int i;		// lv
        int j = i;	// 에러: 지역변수를 초기화 하지 않고 사용
        
//    	int i = 0; // 이렇게 수동 초기화 해줘야 하지않으면 위에처럼 에러발생
    }
}

7) 멤버변수(iv, cv)의 초기화 

(1) 명시적 초기화

  • 변수 선언시 대입연산자를 이용한 초기화
  • 간단한 초기화 시 사용
class Car {
    int door = 4;	// 기본형 변수 초기화
    Engine e = new Engine();	// 참조형 변수의 초기화 -> 객체의 주소를 초기화
    // 참조형 변수에는 객체를 생성하여 선언 해주어야 함.(null 값으로 선언된 상태에서 실행하면 에러발생함)
}

 

(2) 초기화 블럭

  • 복잡한 초기화 시 사용하며 여러 문장을 작성하여 초기화
  • iv (인스턴스) 초기화 블럭 : { }, 거의 사용하지 않음
  • cv(클래스)초기화 블럭 : static { }

(3) 생성자

  • iv초기화 시 사용하며 복잡한 초기화 사용
  • 자주 사용함
// 매개변수가 있는 생성자
Car(String color, String gearType, int door) {
    this.color = color;
    this.gearType = gearType;
    this.door = door;
}

 

(4) 초기화 종류 정리

  1. 자동초기화
  2. 간단한초기화 : = (대입연산자)
  3. 복잡한초기화 : cv = static { } , iv = 생성자, iv 초기화 블럭은 잘 사용 하지 않음 

(5) 스태틱 초기화(cv 초기화) 예시

  • static 배열 변수 arr을 선언 후 static { }를 활용하여 배열 변수의 각 요소에 값을 초기화
class StaticBlockTest {
	static int[] arr = new int[10]; // 명시적 초기화(간단 초기화) -> int타입의 arr 배열 생성
	// arr = cv
    
	static {	// 클래스 초기화(복잡한 초기화) -> 배열 arr을 반복문을 사용하여 난수로 초기화
		for(int i=0;i<arr.length;i++) {
		arr[i] = (int)(Math.random()*10)+1;
	}
}

 

(6) 멤버변수의 초기화 시점

  • 클래스 변수(cv) 초기화 시점 : 클래스가 처음 로딩될 때 한번 (클래스가 메모리에 올라갈 때) 초기화 됨
  • 인스턴스 변수(iv) 초기화 시점 : 인스턴스가 생성될 때 마다 (객체가 만들어질 때 마다) 초기화 됨

(7) 초기화 순서

  • 클래스가 처음 로딩될 때 cv가 먼저 초기화가 되고 인스턴스가 생성되면 iv가 초기화가 됨
  • 자동초기화 -> 간단한 초기화 ( = )-> 복잡한 초기화 (static {} , 생성자) 순서로 초기화가 됨
객체 생성시 초기화 순서 번호 확인

// 1. cv 자동 초기화 (기본값)
// 4. iv 자동 초기화 (기본값)

Class InitTest {
    static int cv = 1;		// 2. cv 명시적 초기화(간단 초기화)
    int iv = 1; 			// 5. iv 명시적 초기화
    
    static { cv = 2;}		//3. cv 복잡한 초기화(static {} 초기화)
    { iv = 2;}				// 6. iv 복잡한 초기화 ({}) - 잘 사용하지 않음
    
    InitTest () { iv = 3;}	// 7. iv 복잡한 초기화(생성자)
    
    InitTest it = new InitTest();	// 객체 생성
}

 

** 출처 : 남궁성의 정석코딩_자바의정석

 

7장 넘어가기전 6장을 요약하여 중요한 부분은 꼭 이해하고 넘어가기! 복습!