객체가 무엇인지 이해하기
일반적인 Java 프로그램은 메서드를 호출하여 상호 작용하는 많은 객체를 생성합니다. 이러한 객체 상호 작용을 통해 프로그램은 GUI 구현, 애니메이션 실행, 네트워크를 통한 정보 송수신 등 다양한 작업을 수행할 수 있습니다. 객체가 생성된 작업을 완료하면 해당 객체의 리소스는 다른 객체가 사용할 수 있도록 재활용됩니다.
다음은 하나의 ‘Point’ 객체와 두 개의 ‘Rectangle’ 객체 등 세 개의 객체를 생성하는 CreateObjectDemo라는 작은 프로그램입니다. 이 프로그램을 컴파일하려면 세 개의 소스 파일이 모두 필요합니다.
public class CreateObjectDemo {
public static void main(String[] args) {
// Declare and create a point object and two rectangle objects.
Point originOne = new Point(23, 94);
Rectangle rectOne = new Rectangle(originOne, 100, 200);
Rectangle rectTwo = new Rectangle(50, 100);
// display rectOne's width, height, and area
System.out.println("Width of rectOne: " + rectOne.width);
System.out.println("Height of rectOne: " + rectOne.height);
System.out.println("Area of rectOne: " + rectOne.getArea());
// set rectTwo's position
rectTwo.origin = originOne;
// display rectTwo's position
System.out.println("X Position of rectTwo: " + rectTwo.origin.x);
System.out.println("Y Position of rectTwo: " + rectTwo.origin.y);
// move rectTwo and display its new position
rectTwo.move(40, 72);
System.out.println("X Position of rectTwo: " + rectTwo.origin.x);
System.out.println("Y Position of rectTwo: " + rectTwo.origin.y);
}
}다음은 Point 클래스입니다:
public class Point {
public int x = 0;
public int y = 0;
// a constructor!
public Point(int a, int b) {
x = a;
y = b;
}
}그리고 Rectangle 클래스입니다:
public class Rectangle {
public int width = 0;
public int height = 0;
public Point origin;
// four constructors
public Rectangle() {
origin = new Point(0, 0);
}
public Rectangle(Point p) {
origin = p;
}
public Rectangle(int w, int h) {
origin = new Point(0, 0);
width = w;
height = h;
}
public Rectangle(Point p, int w, int h) {
origin = p;
width = w;
height = h;
}
// a method for moving the rectangle
public void move(int x, int y) {
origin.x = x;
origin.y = y;
}
// a method for computing the area of the rectangle
public int getArea() {
return width * height;
}
}이 프로그램은 다양한 개체에 대한 정보를 생성, 조작 및 표시합니다. 출력은 다음과 같습니다:
Width of rectOne: 100
Height of rectOne: 200
Area of rectOne: 20000
X Position of rectTwo: 23
Y Position of rectTwo: 94
X Position of rectTwo: 40
Y Position of rectTwo: 72다음 세 섹션에서는 위의 예제를 사용하여 프로그램 내에서 객체의 수명 주기를 설명합니다. 이를 통해 프로그램에서 객체를 생성하고 사용하는 코드를 작성하는 방법을 배우게 됩니다. 또한 수명이 다한 객체를 시스템에서 어떻게 정리하는지 배우게 됩니다.
객체 만들기
아시다시피 클래스는 객체에 대한 청사진을 제공하며, 여러분은 클래스에서 객체를 생성합니다. CreateObjectDemo 프로그램에서 가져온 다음 각 명령문은 객체를 생성하고 이를 변수에 할당합니다:
Point originOne = new Point(23, 94);
Rectangle rectOne = new Rectangle(originOne, 100, 200);
Rectangle rectTwo = new Rectangle(50, 100);첫 번째 줄은 Point 클래스의 객체를 생성하고, 두 번째와 세 번째 줄은 각각 Rectangle 클래스의 객체를 생성합니다.
이러한 각 진술은 세 부분으로 구성되어 있습니다(아래에서 자세히 설명합니다):
- 선언: 굵게 표시된 코드는 모두 변수 이름을 객체 타입과 연결하는 변수 선언입니다.
- 인스턴스화:
new키워드는 객체를 생성하는 Java 연산자입니다. - 초기화:
new연산자 뒤에는 생성자를 호출하여 새 객체를 초기화합니다.
객체를 참조하는 변수 선언하기
앞서 변수를 선언하려면 다음과 같이 작성한다는 것을 배웠습니다:
type name;이는 컴파일러에 데이터 타입이 타입인 데이터를 참조할 때 이름을 사용한다는 것을 알립니다. 원시 변수의 경우 이 선언은 변수를 위한 적절한 양의 메모리도 예약합니다.
참조 변수를 자체 줄에 선언할 수도 있습니다. 예를 들어
Point originOne;이와 같이 originOne을 선언하면 객체가 실제로 생성되어 할당될 때까지 그 값은 결정되지 않습니다. 참조 변수를 선언하는 것만으로는 객체가 생성되지 않습니다. 이를 위해서는 다음 섹션에서 설명하는 대로 new 연산자를 사용해야 합니다. 객체를 코드에서 사용하기 전에 originOne에 객체를 할당해야 합니다. 그렇지 않으면 컴파일러 오류가 발생합니다.
이 상태의 변수는 현재 아무 객체도 참조하지 않습니다.
클래스 인스턴스화하기
new 연산자는 새 객체에 대한 메모리를 할당하고 해당 메모리에 대한 참조를 반환하여 클래스를 인스턴스화합니다. new 연산자는 객체 생성자도 호출합니다.
참고: “클래스 인스턴스화”라는 문구는 “객체 생성”과 같은 의미입니다. 객체를 생성하면 클래스의 “인스턴스”를 생성하는 것이므로 클래스를 “인스턴스화”하는 것입니다.
new 연산자에는 하나의 후위 인자, 즉 생성자에 대한 호출이 필요합니다. 생성자의 이름은 인스턴스화할 클래스의 이름을 제공합니다.
new 연산자는 생성한 객체에 대한 참조를 반환합니다. 이 참조는 일반적으로 다음과 같은 적절한 타입의 변수에 할당됩니다:
Point originOne = new Point(23, 94);new 연산자가 반환하는 참조는 변수에 할당할 필요가 없습니다. 표현식에서 직접 사용할 수도 있습니다. 예를 들어
int height = new Rectangle().height;이 문에 대해서는 다음 섹션에서 설명합니다.
객체 초기화하기
다음은 Point 클래스에 대한 코드입니다:
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int a, int b) {
x = a;
y = b;
}
}이 클래스에는 하나의 생성자가 포함되어 있습니다. 생성자 선언이 클래스와 동일한 이름을 사용하고 반환 타입이 없기 때문에 생성자를 인식할 수 있습니다. Point 클래스의 생성자는 코드 (int a, int b)에서 선언된 대로 두 개의 정수 인수를 받습니다. 다음 문은 이러한 인수의 값으로 23과 94를 제공합니다:
Point originOne = new Point(23, 94);이 문을 실행한 결과는 다음 그림에서 확인할 수 있습니다:

Point 객체
다음은 4개의 생성자가 포함된 Rectangle 클래스의 코드입니다:
public class Rectangle {
public int width = 0;
public int height = 0;
public Point origin;
// four constructors
public Rectangle() {
origin = new Point(0, 0);
}
public Rectangle(Point p) {
origin = p;
}
public Rectangle(int w, int h) {
origin = new Point(0, 0);
width = w;
height = h;
}
public Rectangle(Point p, int w, int h) {
origin = p;
width = w;
height = h;
}
// a method for moving the rectangle
public void move(int x, int y) {
origin.x = x;
origin.y = y;
}
// a method for computing the area of the rectangle
public int getArea() {
return width * height;
}
}각 생성자를 사용하면 원시 및 참조 타입을 모두 사용하여 사각형의 origin, width, height에 대한 초기값을 제공할 수 있습니다. 클래스에 생성자가 여러 개 있는 경우 각 생성자는 서로 다른 서명을 가져야 합니다. Java 컴파일러는 인수의 수와 타입에 따라 생성자를 구분합니다. Java 컴파일러는 다음 코드를 만나면 Point 인자와 두 개의 정수 인수가 필요한 Rectangle 클래스의 생성자를 호출하는 것을 알고 있습니다:
Rectangle rectOne = new Rectangle(originOne, 100, 200);이것은 원점을 originOne으로 초기화하는 Rectangle의 생성자 중 하나를 호출합니다. 또한 생성자는 너비를 100으로, 높이를 200으로 설정합니다. 이제 동일한 Point 객체에 대한 두 개의 참조가 생겼습니다. 다음 그림에서 볼 수 있듯이 객체는 여러 개의 참조를 가질 수 있습니다:

Rectangle 객체
다음 코드 줄은 width와 height의 초기 값을 제공하는 두 개의 정수 인수가 필요한 Rectangle 생성자를 호출합니다. 생성자 내의 코드를 살펴보면 x 및 y 값이 0으로 초기화된 새 Point 객체를 생성하는 것을 볼 수 있습니다:
Rectangle rectTwo = new Rectangle(50, 100);다음 문에서 사용된 Rectangle 생성자는 인수를 받지 않으므로 무인수 생성자라고 합니다:
Rectangle rect = new Rectangle();모든 클래스에는 생성자가 하나 이상 있습니다. 클래스가 명시적으로 생성자를 선언하지 않으면 Java 컴파일러는 기본 생성자라고 하는 인자 없는 생성자를 자동으로 제공합니다. 이 기본 생성자는 클래스 부모의 인자 없는 생성자를 호출하거나, 클래스에 다른 부모가 없는 경우 Object 생성자를 호출합니다. 부모에 생성자가 없는 경우(Object에는 생성자가 있는 경우) 컴파일러는 프로그램을 거부합니다.
객체 사용하기
객체를 만들고 나면 어떤 용도로 사용하고 싶을 것입니다. 필드 중 하나의 값을 사용하거나, 필드 중 하나를 변경하거나, 메서드 중 하나를 호출하여 작업을 수행해야 할 수도 있습니다.
객체의 필드 참조하기
객체 필드는 이름으로 액세스합니다. 모호하지 않은 이름을 사용해야 합니다.
자체 클래스 내에서 필드에 간단한 이름을 사용할 수 있습니다. 예를 들어, Rectangle 클래스 내에 width와 height를 출력하는 문을 추가할 수 있습니다:
System.out.println("Width and height are: " + width + ", " + height);이 경우 width와 height는 단순한 이름입니다.
객체의 클래스 외부에 있는 코드는 다음과 같이 객체 참조 또는 표현식 뒤에 점(.) 연산자를 사용하고 그 뒤에 간단한 필드 이름을 사용해야 합니다:
objectReference.fieldName예를 들어, CreateObjectDemo 클래스의 코드는 Rectangle 클래스의 코드 외부에 있습니다. 따라서 rectOne이라는 Rectangle 객체 내의 origin, width, height 필드를 참조하려면 CreateObjectDemo 클래스에서 각각 rectOne.origin, rectOne.width, rectOne.height라는 이름을 사용해야 합니다. 프로그램은 이 이름 중 두 개를 사용하여 rectOne의 width와 height를 표시합니다:
System.out.println("Width of rectOne: " + rectOne.width);
System.out.println("Height of rectOne: " + rectOne.height);CreateObjectDemo 클래스의 코드에서 width 및 height라는 단순한 이름을 사용하려고 시도하면 이러한 필드는 객체 내에만 존재하므로 의미가 없으며 컴파일러 오류가 발생합니다.
나중에 이 프로그램은 유사한 코드를 사용하여 rectTwo에 대한 정보를 표시합니다. 동일한 타입의 객체에는 동일한 인스턴스 필드의 자체 복사본이 있습니다. 따라서 각 Rectangle 객체에는 origin, width, height라는 필드가 있습니다. 객체 참조를 통해 인스턴스 필드에 액세스하면 해당 특정 객체의 필드를 참조하게 됩니다. CreateObjectDemo 프로그램의 두 객체 rectOne과 rectTwo는 서로 다른 origin, width, height 필드를 가지고 있습니다.
필드에 액세스하려면 이전 예제에서와 같이 객체에 대한 명명된 참조를 사용하거나 객체 참조를 반환하는 표현식을 사용할 수 있습니다. new 연산자는 객체에 대한 참조를 반환한다는 것을 기억하세요. 따라서 new에서 반환된 값을 사용하여 새 객체의 필드에 액세스할 수 있습니다:
int height = new Rectangle().height;이 명령문은 새로운 Rectangle 객체를 생성하고 즉시 그 높이를 가져옵니다. 본질적으로 이 문은 Rectangle의 기본 높이를 계산합니다. 이 문이 실행된 후에는 프로그램이 참조를 어디에도 저장하지 않았기 때문에 생성된 Rectangle에 대한 참조를 더 이상 가지고 있지 않습니다. 객체는 참조되지 않으며 해당 리소스는 Java 가상 머신에서 자유롭게 재활용할 수 있습니다.
객체의 메서드 호출하기
객체 참조를 사용하여 객체의 메서드를 호출할 수도 있습니다. 객체 참조에 메서드의 간단한 이름을 점 연산자(.)를 사용하여 추가합니다. 또한 괄호 안에 메서드에 대한 인수를 제공합니다. 메서드에 인수가 필요하지 않은 경우 빈 괄호를 사용합니다.
objectReference.methodName(argumentList);또는:
objectReference.methodName();Rectangle 클래스에는 직사각형의 면적을 계산하는 getArea()와 직사각형의 원점을 변경하는 move()라는 두 가지 메서드가 있습니다. 다음은 이 두 메서드를 호출하는 CreateObjectDemo 코드입니다:
System.out.println("Area of rectOne: " + rectOne.getArea());
...
rectTwo.move(40, 72);첫 번째 문은 rectOne의 getArea() 메서드를 호출하고 결과를 표시합니다. 두 번째 줄은 move() 메서드가 객체의 origin.x 및 origin.y에 새 값을 할당하기 때문에 rectTwo를 이동합니다.
인스턴스 필드와 마찬가지로 objectReference는 객체에 대한 참조여야 합니다. 변수 이름을 사용할 수 있지만 객체 참조를 반환하는 모든 표현식을 사용할 수도 있습니다. new연산자는 객체 참조를 반환하므로new`에서 반환된 값을 사용하여 새 객체의 메서드를 호출할 수 있습니다:
new Rectangle(100, 50).getArea()new Rectangle(100, 50) 표현식은 Rectangle 객체를 참조하는 객체 참조를 반환합니다. 표시된 것처럼 점 표기법을 사용하여 새 Rectangle의 getArea() 메서드를 호출하여 새 사각형의 면적을 계산할 수 있습니다.
getArea()와 같은 일부 메서드는 값을 반환합니다. 값을 반환하는 메서드의 경우 표현식에서 메서드 호출을 사용할 수 있습니다. 반환 값을 변수에 할당하거나, 의사 결정에 사용하거나, 루프를 제어할 수 있습니다. 이 코드는 getArea()에서 반환된 값을 areaOfRectangle 변수에 할당합니다:
int areaOfRectangle = new Rectangle(100, 50).getArea();이 경우 getArea()가 호출되는 객체는 생성자가 반환하는 rectangle입니다.
가비지 컬렉터
일부 객체 지향 언어에서는 생성한 모든 객체를 추적하고 더 이상 필요하지 않은 경우 명시적으로 파기해야 합니다. 명시적으로 메모리를 관리하는 것은 번거롭고 오류가 발생하기 쉽습니다. Java 플랫폼에서는 원하는 만큼의 개체를 만들 수 있으며(물론 시스템에서 처리할 수 있는 개체에 따라 제한됨), 개체를 삭제하는 것에 대해 걱정할 필요가 없습니다. Java 런타임 환경은 객체가 더 이상 사용되지 않는다고 판단되면 삭제합니다. 이 프로세스를 가비지 컬렉션이라고 합니다.
객체는 해당 객체에 대한 참조가 더 이상 없을 때 가비지 컬렉션을 받을 수 있습니다. 변수에 유지되는 참조는 일반적으로 변수가 범위를 벗어날 때 삭제됩니다. 또는 변수를 특수 값 ‘null’로 설정하여 객체 참조를 명시적으로 삭제할 수도 있습니다. 프로그램에는 동일한 객체에 대한 참조가 여러 개 있을 수 있으며, 객체가 가비지 컬렉션에 포함되기 전에 객체에 대한 모든 참조가 삭제되어야 합니다.
Java 런타임 환경에는 더 이상 참조되지 않는 객체가 사용하는 메모리를 주기적으로 해제하는 가비지 수집기가 있습니다. 가비지 수집기는 적절한 시기가 되었다고 판단되면 자동으로 작업을 수행합니다.