클래스와 객체
- -
- 변수 : 다양한 형태의 데이터를 저장하기 위해 각각의 데이터를 저장할 수 있는 변수라는 문법 요소를 만들어 사용했다.
- 배열 : 데이터의 종류가 많아질수록 데이터의 개수만큼 변수명을 짓거나 관리하는 일이 버거워졌다. 이런 문제를 해결하기 위해 만든 문법 요소가 '배열'이다. 배열을 사용하면 같은 자료형인 변수들을 묶어 1개의 새로운 자료형으로 관리할 수 있으므로 관리해야 할 변수의 개수를 현저하게 줄일 수 있다.
- 구조체 : 배열은 같은 자료의 자료형만 묶을 수 있으므로 반 학생들의 성적(int)과 반 평균(double)은 1개의 배열로 관리할 수 없다. 한 반의 성적 데이터를 한 번에 관리하면 훨씬 효율적일 텐데 말이다. 이를 보완하기 위해 만든 문법 요소가 '구조체struct'다. 구조체를 사용하면 서로 다른 자료형도 1개의 자료형으로 묶어 관리할 수 있다.
- 클래스 : 이렇게 다양한 자료형의 데이터를 하나로 묶어 관리할 수 있는 구조체는 말 그대로 데이터만 묶어 놓은 것이다. 여기에 반 평균 성적을 출력하거나 반 학생들의 총점을 계산하는 등과 같은 기능을 추기하면 반의 성적과 관련된 모든 내용을 효율적으로 처리할 수 있다. 이것이 바로'클래스 class'다. 즉, 클래스는 다양한 자료형의 데이터를 묶어 관리할 수 있을 뿐 아니라 데이터를 처리하는 다양한 기능까지 함께 관리하는 문법 요소다.
클래스의 전체적인 구조를 살펴보기 전에 클래스를 정의하는 방법부터 알아보자. 클래스는 class 키워드와 함께 클래스명을 표기한다. 클래스명은 대문자로 시작하는 것이 관례다.
🐸클래스의 정의
class 클래스명 {
...
}
클래스의 정의를 알아보았으니 다음과 같이 A라는 이름의 클래스를 포함하는 자바 소스 파일 A.java의 구조를 알아보자.
package ...; // 1 패키지
import ...; // 2 임포트
class 클래스명 {...} // 3 외부 클래스
클래스의 밖에 올 수 있는 3가지
public class A(파일명과 동일해야 함){
int a = 3; // 1 필드
double abc() {...} // 2 메서드
A() {...} // 3 생성자
class 클래스명 {...} // 4 이너 클래스
클래스의 안에 올 수 있는 4가지
}
자바 소스 파일은 클래스의 외부 구성 요소와 내부 구성 요소로 나눠 생각할 수 있다.
클래스 외부 구성 요소 살펴보기
클래스의 외부에는 다음 3가지 구성요소만 올 수 있다.
- 패키지 package
: 프로젝트를 생성할 때 패키지를 지정했다면 이 구성 요소에 패키지명이 포함되며, 반드시 주석을 제외하고 첫 번째 줄에 위치해야 한다. 클래스의 생성 과정에서 패키지를 생성하지 않았다면, 즉 디폴트 패키지를 사용하면 생략된다. - 임포트 import
: 다른 패키지의 클래스를 사용하고자 할 때 포함된다. 패키지 다음에 위치한다. - 외부 클래스 external class
: 클래스의 외부에 또 다른 클래스가 포함될 수 있다. 즉 1개의 .java 파일에 여러개의 클래스가 포함될 수 있다는 것이다. 단, 외부 클래스에는 public 키워드를 붙일 수 없다.
클래스 내부 구성 요소 살펴보기
클래스 내부의 구성 요소를 살펴보자. 내부에는 4가지의 구성 요소가 포함될 수 있다.
- 필드 field
: 클래스의 특징(속성)을 나타내는 변수다. 만일 이 클래스가 한 사람에 관련된 정보를 담고 있다면 필드값으로 나이(int age = 20) 등이 포함될 수 있을 것이다. - 메서드 method
: 클래스가 지니고 있는 기능(함수)을 나타낸다. 한 사람에 관련된 클래스라면 일하기(void working() {...})등이 포함될 수 있다. - 생성자 constructor
: 생성자(A() {...})는 클래스의 객체를 생성하는 역할을 담당한다. 아직 클래스나 객체에 관한 명확한 개념은 없더라도 생성자의 역할이 '객체를 생성한다'라는 점까지는 기억해 두자. - 이너 클래스 class
: 클래스의 내부에도 클래스가 포함될 수 있다. 이 클래스를 특별히 '이너 클래스'라고 한다.
내부에 올 수 있는 4가지 구성 요소들 중 생성자를 제외한 3가지 요소를 '클래스의 멤버 member'라고 한다. 정리하면 클래스의 외부에는 3가지 종류, 내부에는 4가지 종류만 올 수 있으며, 이들 모두 또는 일부만 있어도 되고, 심지어 하나도 포함되지 않아도 문법적으로는 문제가 없다. 그러나 이들 이외의 요소가 한 글자라도 들어 있다면 컴파일러는 뒤도 안 돌아보고 오류를 발생시킬 것이다.
+) 접근 지정자 public 이란?
class 키워드 앞에 있는 public을 접근 지정자 라고 한다. 이는 다음에 자세히 다룰 것이므로 여기서는 class를 꾸며 주는 말 정도로만 생각하면 된다. 즉, 빨간색 사과 라는 표현에서 사과가 클래스라면 public은 빨간 정도의 의미를 지니고 있는 것이다. 다만 .java 파일 내에서 pulic은 최대 1개의 클래스에만 붙을 수 있으며 public이 붙은 클래스명이 파일명과 동일해야 한다는 정도는 꼭 기억하자.
우리는 클래스를 직접 사용할 수 없다. 클래스의 모든 특징(필드)과 기능(메서드)들을 사용하려면 클래스를 이용해 객체를 만든 후 그 객체 속의 필드와 메서드 등을 사용해야 하는 것이다.
클래스에서 객체를 만드는 과정은 생성자가 수행한다. 클래스의 생성자로 객체를 만드는 과정을 '인스턴스화 instantiation'라고 하고 인스턴스화로 만들어진 객체를 '인스턴스 instance'라고 한다. 객체(붕어빵)속에는 클래스의 내부 구성 요소 중 생성자를 제외한 나머지 요소가 포함돼 있는데 이를 '인스턴스 멤버 instance memeber'라고 한다. 이 시점에서 '클래스는 바로 사용할 수 없고 반드시 객체를 생성해 객체 안에 있는 필드, 메서드 및 이너 클래스를 사용해야 한다.'는 점을 꼭 기억하자
객체 생성하기
객체는 new 키워드로 생성할 수 있다. 자바에서는 대부분의 클래스가 이 방법으로 객체를 생성한다. 클래스에 따라 메서드를 사용해 객체를 생성할 때도 있지만 이때도 해당 메서드 내부에서 new를 사용해 객체를 생성한다. 즉 모든 클래스가 객체를 new 키워드로 생성한다고 볼 수 있다.
🐶클래스의 객체 생성
클래스명 참조 변수명 = new 생성자();
예 A a = new A();
객체 생성 코드를 구성하는 요소를 앞에서부터 살펴보자. 첫 번째는 클래스명, 두 번째는 참조 변수다. 참조 변수는 실제 데이터를 저장하는 것이 아니라 실제 데이터가 있는 힙 메모리의 위칫값을 가리키는 변수를 말한다고 했다. 세 번째는 new 키워드로 '~을 힙 메모리에 넣어라'는 의미다. 마지막은 생성자다. 클래스와 이름이 동일하지만 뒤에 소괄호가 붙어있다.
이 생성자가 실행되면 클래스의 객체가 생성된다. 따라서 new는 생성자의 결과물로 나온 객체를 힙 메모리에 넣는다.
그런데 실제 데이터를 저장하고 있는 객체를 힙 메모리의 어느 위치에 넣었는지 알려 주지 않으면 그 객체를 쓸 방법이 없다. 그래서 힙 메모리에 실제 객체를 넣을 때 그 위칫값을 변수에게 알려 주는 것이다. 위 객체 생성 예시에 포함된 코드를 다시 한번 말로 표현하면 'A() 생성자로 만든 객체를 힙 메모리에 넣고 위칫값을 A 타입의 참조 변수 a에 저장하라.'고 표현할 수 있다. 몇 줄 안 되는 설명이지만 어쩌면 책에서 가장 중요한 부분일 수 있다. 자바는 클래스 기반이고 모든 클래스에 적용되기 때문이다.
객체 생성에 따른 메모리 구조 살펴보기
이제 객체를 생성했을 때 메모리에 어떻게 저장되는지를 그림을 이용해 살펴보자.
클래스 A는 메모리의 클래스 영역, 참조 변수는 스택 영역에 들어간다. 내부 공간에는 실제 데이터(객체)의 위칫값을 저장한다. 생성자로 만들어진 객체는 힙 메모리에 위치하며 객체 내부에는 클래스의 멤버(필드, 메서드, 이너 클래스)가 위치한다. 이제 객체에 포함된 3가지 요소가 사용할 수 있는 상태가 된 것이다. 그런데 메서드를 살펴보면 실제 메서드 구현 코드는 클래스 영역 안에 저장해 놓고, 객체 안에서는 메서드 영역의 위치만 가리키고 있다는 것을 알 수 있다. 그 이유는 1개의 클래스로 만든 모든 객체는 속성(필드)은 달라도 기능(메서드)는 동일하기 때문이다. 즉, 객체를 100개 만들어도 메서드는 한 번만 만들면 된다는 뜻이다. 자동차 클래스로 빨간색 자동차와 파란색 자동차를 하나씩 만드는 그림을 살펴보자.
자동차 클래스로 빨간색 자동차 객체와 파란색 자동차 객체를 만들면 힙 메모리에 각 객체가 저장된다. 빨간색 자동차의 color 속성값은 'red', 파란색 자동차의 color 속성값은 'blue'라고 가정해 보자. 둘다 drive(기능)이 있어야 하므로 두 객체 안에 drive()메서드가 포함돼 있어야 한다. 그런데 각 객체에 포함돼 있는 drive()메서드 코드가 동일하므로 이를 메서드 영역에 1개만 만들어두고 모든 객체가 공유하는 것이다.
여기서 '자동차마다 성능이 다르지 않아요?', '성능이 다르면 drive() 메서드도 다르지 않나요?'와 같은 질문을 하는 사람도 있을 수 있다. 당연하다. 하지만 성능이 다르다는 건 다른 클래스의 객체라는 의미다. 즉, '다른 붕어빵 기계로 찍은 붕어빵'이라는 이야기다. 다른 클래스로 생성된 객체의 메서드이므로 당연히 메서드를 공유하지 않는다. 다시 말해, 동일한 클래스로 만든 객체들은 기능(메서드)의 내용이 동일하므로 메서드를 공유할 수 있는 것이다.
클래스의 객체 생성 코드와 객체 생성 이후의 메모리 구조는 그림과 같다.
앞에서 살펴본 예제를 실제 데이터로 바꾼 정도이므로 쉽게 이해될 것이다. 여기서는 생성된 객체에서 필드값은 실제 저장공간이 객체 내부에 있고, 메서드는 메서드 영역에 있는 1개의 메서드를 공유하고 있다는 점만 기억하자.
출처 : Do it! 자바 완전 정복
저자 : '김동형'
'개인공부 > Java' 카테고리의 다른 글
클래스 내부 구성 요소 : 메서드 (0) | 2022.07.18 |
---|---|
클래스의 내부 구성 요소 : 변수 (0) | 2022.07.18 |
참조 자료형 String (0) | 2022.07.18 |
참조 자료형 1차배열 (0) | 2022.07.15 |
연산자 (0) | 2022.07.14 |
소중한 공감 감사합니다