객체가 생성될 때 호출되며 객체를 초기화하는 역할을 수행
- 생성자 선언과 호출
- 리턴 타입이 없고 생성자명은 클래스의 이름과 동일
new
연산자에 의해 객체가 생성되면, 생성자가 호출됨public Car() {} // 선언 Car car = new Car(); // 호출
선언할 때 괄호 안에 아무 것도 넣지 않은 생성자
- 모든 클래스는 반드시 생성자가 하나 이상 존재
- 클래스에 생성자를 하나도 선언하지 않았다면, 컴파일러가 기본 생성자를 자동으로 추가(따라서, 기본 성성자는 생략이 가능)
- 하나라도 생성자가 선언되어 있다면, 컴파일러는 기본 생성자를 추가해주지 않음
- 컴파일러에 의해 생성되는 기본 생성자는 해당 클래스의 접근제어자를 따름
public class Car { public Car(String model) {} // 생성자 선언 // 생성자가 한개 이상 선언되었기 때문에 기본 생성자를 추가하지 않음 }
public class Car { // 컴파일러가 추가시켜준 기본 생성자라면 // 접근제어자는 클래스와 같은 public public Car() {} }
- 생성자는 객체를 초기화하는 역할을 수행하기 때문에 객체를 만들 때 인스턴스마다 다른 값을 가져야 한다면, 생성자를 통해서 필드를 초기화할 수 있음
- 인스턴스마다 동일하나 데이터를 가지는 필드가 있다면, 초기값을 대입하는 것이 좋음
- 필드값을 초기화하는 생성자만 만들었다면 기본 생성자 호출 시 에러 발생(생성자가 존재하여 컴파일러가 기본 생성자를 만들어 주지 않기 때문에)
public Car(String modelName, String colorName, double priceValue) { model = modelName; color = colorName; price = priceValue; } ... Car car = new Car(); // 에러 발생
- 생성자를 통해 필드를 초기화할 때 오버로딩 적용 가능
// 오버로딩 시에는 매개변수 개수, 타입, 순서 중요 public Car(String modelName, String colorName) {} public Car(String modelName, String colorName, double priceValue) {}
- this는 객체 즉, 인스턴스 자신을 표현
- 객체 내부 생성자 및 메소드에서 객체 내부 멤버에 접근하기 위해 사용
public Car(String model, String color, double price) { model = model; color = color; price = price; }
- 위의 예시처럼 생성자를 선언했다면 에러가 발생하지는 않지만, 생성자 블록 내부에서 해당 변수들은 객체의 필드가 아닌 가장 가까운 매개변수명을 가리키게 됨으로 자기 자신에게 값을 저장하게 됨
public Car(String model, String color, double price) { this.model = model; this.color = color; this.price = price; }
- 이럴 경우 this를 통해 객체의 필드에 접근하고 매개변수의 값을 객체의 필드에 저장 가능
- 객체의 메소드에서 리턴 타입이 인스턴스 자신의 클래스 타입이라면 this를 사용하여 자신의 주소를 리턴할 수도 있음
Car returnInstance() { return this; }
- this()는 객체 즉, 인스턴스 자신의 생성자를 호출
- 객체 내부 생성자 및 메소드에서 해당 객체의 생성자를 호출하기 위해 사용될 수 있으며, 생성자를 통해 객체의 필드를 초기화할 때 중복되는 코드를 줄일 수 있음
// this() 사용 전 public Car(String model) { this.model = model; this.color = "Blue"; this.price = 50000000; } public Car(String model, String color) { this.model = model; this.color = color; this.price = 50000000; } public Car(String model, String color, double price) { this.model = model; this.color = color; this.price = price; } 👇 // this() 사용 후 public Car(String model) { this(model, "Blue", 50000000); } public Car(String model, String color) { this(model, color, 100000000); } public Car(String model, String color, double price) { this.model = model; this.color = color; this.price = price; }
⚠️ 단, this()를 사용해서 다른 생성자를 호출할 때는 반드시 첫 줄에 작성되어야 함
public Car(String model) { // this()가 첫 줄이 아니기 때문에 에러 발생 System.out.println("model = " + model); this(model, "Blue", 50000000); }
public
, protected
, default
, private
static
, final
, abstract
- 멤버 또는 클래스에 사용하여 외부에서의 접근을 제한함
- 클래스, 멤버 변수, 메소드, 생성자에 사용되며 지정하지 않는다면
default
가 지정됨
- public : 접근 제한이 없음(누구나 접근 가능)
- protected : 같은 패키지 내 또는 다른 패키지의 자손 클래스에서 접근 가능
- default : 같은 패키지 내에서만 접근 가능
- private : 같은 클래스 내에서만 접근 가능
- 사용 가능한 접근 제어자를 분류하면 아래와 같음
- 클래스 :
public
,default
- 메소드, 멤버변수 :
public
,protected
,default
,private
- 지역변수 : 없음
Getter
: 외부에서 객체의 private
한 필드를 읽을 필요가 있을 때 사용
Setter
: 외부에서 객체의 private
한 필드에 데이터를 저장/수정할 필요가 있을 때 사용
getter
의 경우 메소드명을get + 필드명
으로 지정setter
의 경우 메소드명을set + 필드명
으로 지정- 사용 방법은 인스턴스 메소드 호출과 동일
private String speed; private double price;
// Getter public String getSpeed() { return speed; } public double getPrice() { return price; } // Setter public String setSpeed(String speed) { this.speed = speed; } public double setPrice(double price) { this.price = price; }
- 사용 가능한 제어자
- 클래스 :
public
,default
,final
,abstract
- 메소드 :
public
,protected
,default
,private
,final
,abstract
,static
- 멤버 변수 :
public
,protected
,default
,private
,final
,static
- 지역변수 :
final
패키지는 클래스의 일부분이며 클래스를 식별해주는 용도
- 패키지는 상위 패키지와 하위 패키지를 도트(.)로 구분
package 상위 패키지.하위 패키지;
로 선언package oop.pk1; public class Car { public void horn() { System.out.println("pk1 빵빵"); } }
package oop.pk2; public class Car { public void horn() { System.out.println("pk2 빵빵"); } }
package oop.main; public class Main { public static void main(String[] args) { // pk1과 pk2 모두 Car 클래스를 가지고 있는 경우, 패키지의 경로로 구분 oop.pk1.Car car = new oop.pk1.Car(); car.horn(); // pk1 빵빵 oop.pk2.Car car2 = new oop.pk2.Car(); car2.horn(); // pk2 빵빵 } }
import는 다른 패키지에 있는 클래스를 사용하기 위해 명시하는 키워드
import 다른 패키지에 있는 클래스의 경로
로 선언*
을 사용하면 패키지 안에 있는 모든 클래스 사용 가능package oop.main; import oop.pk1.Car; // import oop.pk1.*; // pk1의 패키지에 있는 모든 클래스 사용 가능 public class Main { public static void main(String[] args) { Car car = new Car(); car.horn(); // pk1 빵빵 oop.pk2.Car car2 = new oop.pk2.Car(); car2.horn(); // pk2 빵빵 } }