생성자란?
기본생성자?
모든 Class는 생성자가 반드시 존재하고, 하나 이상을 가질 수 있음
Class내부에 생성자 선언을 생략했다면, Compiler(컴파일러)는 중괄호 {} 블록 내용이 비어있는 Default Constructor(기본 생성자)를 바이트 코드에 자동 추가시킴
// 바이트코드 내부
[public] Class() {}
클래스가 public class로 선언되면 기본 생성자에도 public이 붙지만, 클래스가 public없이 class로만 선언되면 기본 생성자에도 public이 붙지 않음!
[예제]
// 소스파일 => Test.java
public class Test {}
// 바이트 코드 파일 => Test.class
public class Test {
public Test() { } // 자동으로 추가됨
// ↑
// 기본 생성자
}
클래스에 생성자를 선언하지 않아도, new 연산자 뒤에 기본 생성자를 호출해서 Object(객체)를 생성 시킬 수 있음! ⇒ Test myTest = new Test(); // Test() : 기본 생성자임
클래스에 **명시적으로 선언한 생성자(Constructor)**가 한 개라도 존재하면, Compiler(컴파일러)는 기본 생성자를 추가하지 않으며, 생성자를 선언하는 이유는 Object(객체)를 다양하게 초기화하기 위해서임
생성자 선언(생성자 명시)
기본 생성자 대신 생성자를 명시적으로 선언할려면 예제처럼 작성해야함!
[예제]
Class(매개변수선언, ...) { // 생성자 블록
// Object(객체)초기화 코드
}
// 메소드와 비슷한 모양을 가지지만, 반환 타입이
// 없으며 Class이름과 동일함
// 생성자 블록 내부에는 Object(객체)초기화 코드가
// 작성되고, 일반적으로 필드에 초기값을 저장하거나
// 메소드를 호출하여 Object(객체)사용 전에 필요한
// 준비를 하고, 매개변수 선언은 생략이 가능하고,
// 여러 개를 선언도 할 수 있음!
// 매개변수는 new 연산자로 생성자 호출 시 외부의값
// 생성자 블록 내부로 전달하는 역할을 함
ex)
Test myTest = new Test("Hello", "Black", 2);
Class 생성자가 명시적으로 선언되었을 경우, 반드시 선언된 생성자를 호출해서 Object(객체)를 생성해야만 함!
[예제]
// 생성자 선언 => Test.java
public class Test{
// Constructor
Test(String strTest, int iTest){ }
}
// 생성자를 호출해서 객체 생성
// => TestExample.java
public class TestExample {
public static void main(String[] args) {
Test myTest = new Test("Black", 2);
// Test myTest : 기본 생성자는 호출 X
}
}
필드(Field)초기화?
[예제]
// Noddle Class
public class Noddle {
// Member Variable[멤버변수]
String noddleName = "열라면";
String soup;
String price;
// Constructor[생성자]
public Noddle(String soup, String price) {
this.soup = soup;
this.price = price;
}
}
관례적으로 필드와 동일한 이름을 갖는 매개변수를 사용하고, 생성자 내부에서 해당 필드에 접근할 수 없음!
동일한 이름의 매개변수가 사용 우선순위가 높기 때문이고, 해결방법은 “this.”을 붙여주면 됨!
생성자 오버로딩(Overloading)
외부에서 제공되는 다양한 데이터들을 이용해서 Object(객체)를 초기화하려면, 생성자도 다양화될 필요가 있음!
생성자가 하나뿐이라면 두 가지 경우에 따라 객체를 모두 생성 할 수 없음!
매개변수를 달리는 생성자를 여러개 선언이 가능하도록 하는 것을 말함
[예제]
// Test Class에서의 생성자 오버로딩
public class Test {
Test() {...}
Test(String one) {...}
Test(String one, String two){...}
}
[주의]
매개변수의 타입과 개수, 선언된 순서가 똑같을 경우에 매개변수 이름만 바꾸는 행위는 생성자 오버로딩으로 볼 수 가 없음!(구분 X)
[예제]
Test(String one, String two){...}
// 오버로딩이 아님!
Test(String one, String thrid){...}
생성자가 오버로딩 되어 있을 경우, new 연산자로 생성자를 호출 할때, 제공되는 매개값의 타입과 개수에 의해 호출될 생성자가 결정이 됨
[예제]
// Noddle Class
public class Noddle {
// 필드
String noddleName = "열라면";
String soup;
String price;
// 기본생성자
public Noddle() {}
// 생성자1
public Noddle(String soup) {
// 필드에 매개변수 값 저장함
this.soup = soup;
}
// Constructor[생성자 오버로딩]
public Noddle(String soup, String price) {
// 필드에 매개변수 값 저장함
this.soup = soup;
this.price = price;
}
}
// NoddleExample Class
public class NoddleExample {
public static void main(String[] args) {
// 기본생성자(생성자1)
Noddle ramen = new Noddle();
// 열라면
System.out.println(ramen.noddleName);
// 생성자2
Noddle ramen = new Noddle("너구리");
// 너구리
// 매콤한맛
System.out.println(ramen.noddleName);
System.out.println(ramen.soup);
// 생성자3
Noddle ramen = new Noddle("진라면");
// 진라면
// 순한맛
// 1500원
System.out.println(ramen.noddleName);
System.out.println(ramen.soup);
System.out.println(ramen.price);
}
}
다른 생성자 호출 this()?
생성자 오버로딩이 많아질 경우 생성자간 중복 코드가 많아지는데, 매개변수만으로 다르게 하고 필드 초기화 내용이 비슷한 생성자에서 이런 현상이 주로 발생하며, 해결방법은 필드 초기화 내용은 한 생성자에서만 작성하고, 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선할 수 있음
this() : 자신의 다른 생성자를 호출하는 코드로 반드시 생성자의 첫 줄에서만 허용이되고, 매개값은 호출되는 생성자의 매개변수 타입에 맞게 제공해야함, 그리고 추가적으로 실행문들이 그 다음으로 들어 옴!
[예제]
// Noddle Class
public class Noddle {
// 필드
String noddleName = "열라면";
String soup;
String price;
// 기본생성자
public Noddle() {}
// 생성자1
public Noddle(String noddleName) {
// 필드에 매개변수 값 저장함
// 생성자1, 생성자3
this(noddleName, "매운맛", 1600);
}
// Constructor[생성자2]
public Noddle(String noddleName, String soup) {
// 필드에 매개변수 값 저장함
// 생성자2, 생성자3
this(noddleName, soup, 1800);
}
// Constructor[생성자3]
public Noddle(String noddleName, String soup, String price) {
// 필드에 매개변수 값 저장함
// 공통 실행 코드
this.noddleName = noddleName;
this.soup = soup;
this.price = price;
}
}
// NoddleExample Class
public class NoddleExample {
public static void main(String[] args) {
// 기본생성자(생성자1)
Noddle ramen = new Noddle();
// 열라면
System.out.println(ramen.noddleName);
// 생성자2
Noddle ramen = new Noddle("너구리", "매콤한맛");
// 너구리
// 매콤한맛
System.out.println(ramen.noddleName);
System.out.println(ramen.soup);
// 생성자3
Noddle ramen = new Noddle("진라면", "순한맛", 1700);
// 진라면
// 순한맛
// 1700원
System.out.println(ramen.noddleName);
System.out.println(ramen.soup);
System.out.println(ramen.price);
}
}