1단계: 메모리 할당
-- new 키워드를 사용하여 Heap 영역에 메모리 할당
-- 생성자 호출
2단계: 생성자를 사용하여 객체 초기화
-- 클래스 이름과 괄호를 사용
Date now = new Date();
클래스에 생성자를 작성하지 않으면 기본 생성자가 생성됨
-- public 접근 제한
-- 클래스와 이름이 같음
-- return 타입이 없음 – void가 아님
-- 파라미터가 없음
-- 모든 필드는 기본 값으로 초기화
class Date {
private int year, month, day;
/*
public Date( ) {
year = 0;
month = 0;
day = 0;
}
*/
}
class Test {
public static void main(String[] args) {
Date today = new Date();
}
}
상속되는 기본 생성자 대신 객체만의 기본 생성자를 정의
class Date {
private int year, month, day;
public Date() {
year = 1971;
month = 04;
day = 28;
}
}
생성자는 메소드이므로, 오버로딩 할 수 있음
-- 같은 범위, 같은 이름, 다른 파라미터를 사용하여 정의
-- 객체가 다른 방법으로 초기화 되는 것을 허용
주의 : 생성자를 정의하면, 컴파일러는 기본 생성자를 정의하지 않음
class Overload {
public int data;
public Overload() {}
public Overload(int data) {
this.data = data;
}
}
class Test {
static void main() {
Overload o1 = new Overload();
Overload o2 = new Overload(28);
}
}
class Date {
public Date() {
this(1971, 04, 28);
}
public Date(int year, int month, int day){
...
}
}
초기자 목록(initializer list)이라는 특수 구문을 사용하여 한 생성자에서 오버로드된 다른 생성자를 호출하여 생성자를 구현할 수 있습니다.
class Date {
private int year, month, day;
public Date() {
this.year = 1070;
this.month = 4;
this.day = 28;
}
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
class Date {
private int year, month, day;
public Date() {
init(1971, 04, 28);
}
public Date(int year, int month, int day) {
this.init(year, month, day);
}
private void init(intt year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
상수 변수는 절대로 변하지 않는 값을 나타내며, final 키워드를 사용하여 선언
public class Calculator {
final double pi = 3.14;
final double tau = pi * 2;
public double getAreaOfCircle(double radius) {
return radius * radius * pi;
}
public double getCircumference(double radius) {
return radius * tau;
}
}
생성자는 private으로도 선언할 수 있습니다.
class Math {
public static double Sin(double a) { … }
public static double Cos(double a) { … }
private Math() {}
}
class Test {
public static void main(String[] args) {
double result = math.Cos(28);
}
}
Sin 과 Cos 를 정적 메소드로 선언하면, 이름 공간이 정해진 함수와 유사하게 정의할 수 있습니다. static 메소드는 정적으로 동작하므로 클래스의 인스턴스가 생성될 필요 없습니다.
객체 생성
-- new 키워드를 사용하여 메모리에 객체 할당
-- 생성자를 사용하여 메모리에서 객체 초기화
이때 객체의 상태는 Created가 됩니다.
객체 사용
-- 메소드 호출 등
In use or reachable (사용 중)
Invisible (사용 중이며 접근 불가)
Unreachable (사용되지 않음)
객체 제거
-- 원시 메모리 회수
-- 메모리 할당 해제
Collected (가비지 컬렉터의 대상이 됨)
Finalized (제거)
Deallocated (메모리 해제)
class Example {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
int j = 0;
}
j = 28; // 컴파일시 오류
}
}
class Example {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Example example = new Example();
}
// example은 범위 밖에 있습니다.
// example에는 도달할 수 없지만 존재합니다. (invisible)
}
}
Stack에 할당되고 범위의 끝에서 소멸되는 int와 같은 값과는 달리 객체는 관리되는 Heap에 할당되고 범위의 끝에 해당되어도 소멸되지 않습니다.
객체는 명시적으로 소멸시킬 수 없음
-- Java는 객체 생성 키워드와 반대의 동작을 하는 키워드(delete 등)가 없음
-- 명시적 삭제 기능은 다른 언어에서 치명적 어류의 주요 원인이 됨
가비지 컬렉션이 프로그래머를 대신하여 객체를 제거
-- 도달할 수 없는 객체를 찾아 자동으로 제거
-- 사용되지 않는 Heap 메모리로 되돌리고(메모리를 반환하고) 마무리함
-- 일반적으로 메모리가 부족할 때 가비지 컬렉션 작업을 수행