클래스가 필요한 이유
자바 세상은 클래스와 객체로 이루어져 있다. 그만큼 클래스와 객체라는 개념은 중요하다. 우선 클래스와 객체라는 개념이 왜 필요한 지부터 시작해서 클래스가 어떤 방식으로 발전하면서 만들어졌는지 점진적으로 알아보려고 한다.
예시 코드로 이해
public class ClassStart1 {
public static void main(String[] args) {
String student1Name = "학생1";
int student1Age = 15;
int student1Grade = 90;
String student2Name = "학생2";
int student2Age = 16;
int student2Grade = 80;
String student3Name = "학생3";
int student3Age = 17;
int student3Grade = 80;
System.out.println("이름: " + student1Name + " 나이: " + student1Age + " 성적: " + student1Grade);
System.out.println("이름: " + student2Name + " 나이: " + student2Age + " 성적: " + student2Grade);
System.out.println("이름: " + student3Name + " 나이: " + student3Age + " 성적: " + student3Grade);
}
}
- 위 코드의 문제점은 학생이 늘어날 때마다 변수를 추가로 선언해야 하고, 또 출력하는 코드도 추가해야 한다.
위의 예시코드를 배열로 개선
public class ClassStart2 {
public static void main(String[] args) {
String[] studentNames = {"학생1", "학생2", "학생3"};
int[] studentAges = {15, 16, 17};
int[] studentGrades = {90, 80, 80};
for (int i = 0; i < studentNames.length; i++) {
System.out.println("이름: " + studentNames[i] + " 나이: " + studentAges[i] + " 성적: " + studentGrades[i]);
}
}
}
- 배열을 사용해서 코드 변경을 최소화하는 데는 성공했지만,
- 아직 데이터를 변경할 때 매우 조심해서 작업해야 한다는 문제점이 있다. (예를 들어서 학생 2의 데이터를 제거하려면 각각의 배열마다 정확하게 학생 2의 요소만 제거해야 함.)
: 사람이 관리하기 좋은 방식은 학생이라는 개념을 하나로 묶는 것이다. 이제 클래스를 도입해서 해결해 보자.
클래스 도입
앞서 이야기한 문제를 클래스를 도입해서 해결해 보자.
클래스를 사용해서 학생이라는 개념을 만들고, 각각의 학생 별로 본인의 이름, 나이, 성적을 관리하는 것이다.
Student 클래스
public class Student {
String name;
int age;
int grade;
}
- class 키워드를 사용해서 학생 클래스(Student)를 정의한다. 내부에는 name, age, grade라는 변수를 가진다.
이렇게 클래스에 정의한 변수들을 멤버 변수, 또는 필드라 한다.
- 멤버 변수: 이 변수들은 특정 클래스에 소속된 멤버이기 때문에 이렇게 부른다.
- 필드: 데이터 항목을 가르키는 전통적인 용어이다. 데이터베이스, 엑셀 등에서 데이터 각각의 항목을 필드라 한다.
- 자바에서 멤버 변수, 필드는 같은 뜻이다. 클래스에 소속된 변수를 뜻한다.
클래스는 관례상 대문자로 시작하고 낙타 표기법을 사용한다.
Student(학생) 클래스를 이용하는 예제 코드
public class ClassStart3 {
public static void main(String[] args) {
Student student1 = new Student();
student1.name = "학생1";
student1.age = 15;
student1.grade = 90;
Student student2 = new Student();
student2.name = "학생2";
student2.age = 16;
student2.grade = 80;
System.out.println("이름: " + student1.name + " 나이: " + student1.age + " 성적: " + student1.grade);
System.out.println("이름: " + student2.name + " 나이: " + student2.age + " 성적: " + student2.grade);
}
}
클래스와 사용자 정의 타입
- 타입은 데이터의 종류나 형태를 나타낸다.
- int라고 하면 정수 타입, String이라고 하면 문자 타입이다.
- 학생(Student)이라는 타입을 만들면 되지 않을까?
- 클래스를 사용하면 int, String과 같은 타입을 직접 만들 수 있다.
- 사용자가 직접 정의하는 사용자 정의 타입을 만들려면 설계도가 필요하다. 이 설계도가 바로 클래스이다.
- 설계도인 클래스를 사용해서 실제 메모리에 만들어진 실체를 객체 또는 인스턴스라 한다.
- 클래스를 통해서 사용자가 원하는 종류의 데이터 타입을 마음껏 정의할 수 있다.
여기서는 학생(Student) 클래스를 기반으로 학생 1(student1), 학생 2(student2) 객체 또는 인스턴스를 만들었다.
코드를 하나씩 분석
객체 생성
- 객체를 사용하려면 먼저 설계도인 클래스를 기반으로 객체(인스턴스)를 생성해야 한다.
- `new Student()`: new는 새로 생성한다는 뜻이다. `new Student()`는 Student 클래스 정보를 기반으로 새로운 객체를 생성하라는 뜻이다. 이렇게 하면 메모리에 실제 Student 객체(인스턴스)를 생성한다.
- Student 클래스는 String name, int age, int grade 멤버 변수를 가지고 있다. 이 변수를 사용하는데 필요한 메모리 공간도 함께 확보한다.
참조값 보관
- 객체를 생성하면 자바는 메모리 어딘가에 있는 이 객체에 접근할 수 있는 참조값(주소)(x001)을 반환한다.
(x001은 이해를 돕기 위한 예시이다.) - new 키워드를 통해 객체가 생성되고 나면 참조값을 반환한다. 앞서 선언한 변수인 Student student1이 생성된 객체의 참조값(x001)을 보관한다.
- student1 변수는 이제 메모리에 존재하는 실제 Student 객체(인스턴스)의 참조값을 가지고 있다. 쉽게 이야기해서 student1 변수를 통해 메모리에 있는 실제 객체를 접근하고 사용할 수 있다.
참조값을 변수에 보관해야 하는 이유
`new Student()` 이 코드는 단순히 메모리에 실제 객체를 만드는 것이다. 따라서 생성한 객체에 접근할 수 있는 방법이 필요하다. 이런 이유로 객체를 생성할 때 반환되는 참조값을 어딘가에 보관해야 하고 변수에 참조값을 저장해 두었으므로 참조값을 통해 실제 메모리에 존재하는 객체에 접근할 수 있다.
간단 정리
Student student1 = new Student(); //1. Student 객체 생성
Student student1 = x001; //2. new Student()의 결과로 x001 참조값 반환
student1 = x001; //3. 최종 결과
객체 사용
클래스를 통해 생성한 객체를 사용하려면 먼저 메모리에 존재하는 객체에 접근해야 한다. 객체에 접근하려면 `.`(점, dot)을 사용하면 된다.
객체에 값 대입
객체가 가지고 있는 멤버 변수(name, age, grade)에 값을 대입하려면 먼저 객체에 접근해야 한다.
객체에 접근하려면 위에서 말했듯이 `.` 키워드를 사용하면 된다. 이 키워드는 변수(student1)에 들어있는 참조값(x001)을 읽어서 메모리에 존재하는 객체에 접근한다.
코드로 이해
student1.name="학생1" //1. student1 객체의 name 멤버 변수에 값 대입
x001.name="학생1" //2.변수에 있는 참조값을 통해 실제 객체에 접근, 해당 객체의 name 멤버 변수에 값 대입
그림으로 이해
객체 값 읽기
객체의 값을 읽는 것도 앞서 설명한 내용과 같다. `.` 키워드를 통해 참조값을 사용해서 객체에 접근한 다음에 원하는 작업을 하면 된다.
코드로 이해
//1. 객체 값 읽기
System.out.println("이름:" + student1.name);
//2. 변수에 있는 참조값을 통해 실제 객체에 접근하고, name 멤버 변수에 접근한다.
System.out.println("이름:" + x001.name);
//3. 객체의 멤버 변수의 값을 읽어옴
System.out.println("이름:" + "학생1");
그림으로 이해
클래스, 객체, 인스턴스 정리
클래스 - class
클래스는 객체를 생성하기 위한 '틀' 또는 '설계도'이다. 클래스는 객체가 가져야 할 속성(변수)과 기능(메서드)을 정의한다. 예를 들어 학생이라는 클래스는 속성으로 name, age, grade를 가진다.
- 붕어빵 틀은 붕어빵이 아니다! 이렇게 생긴 붕어빵이 나왔으면 좋겠다고 만드는 틀일 뿐이다. 실제 먹을 수 있는 것이 아니다. 실제 먹을 수 있는 붕어빵은 객체 또는 인스턴스라 한다.
객체 - Object
객체는 클래스에서 정의한 속성과 기능을 가진 실체이다. 객체는 서로 독립적인 상태를 가진다.
예를 들어 위 코드에서 student1과 student2는 같은 클래스에서 만들어졌지만, 서로 다른 객체이다.
인스턴스 - Instance
인스턴스는 특정 클래스로부터 생성된 객체를 의미한다. 그래서 객체와 인스턴스라는 용어는 자주 혼용된다. 인스턴스는 주로 객체가 어떤 클래스에 속해 있는지 강조할 때 사용한다. 예를 들어 "student1 객체는 Student 클래스의 인스턴스다."라고 표현한다.
배열 도입
클래스와 객체 덕분에 학생 데이터를 구조적으로 이해하기 쉽게 변경할 수 있었다.
이제는 Student 클래스를 사용한 변수들도 Student 타입이기 때문에 배열을 사용해서 하나의 데이터 구조로 묶어서 관리할 수 있다.
예제 코드
public class ClassStart4 {
public static void main(String[] args) {
Student student1 = new Student();
student1.name = "학생1";
student1.age = 15;
student1.grade = 90;
Student student2 = new Student();
student2.name = "학생2";
student2.age = 16;
student2.grade = 80;
Student[] students = new Student[2];
students[0] = student1;
students[1] = student2;
System.out.println("이름: " + students[0].name + " 나이: " + students[0].age + " 성적: " + students[0].grade);
System.out.println("이름: " + students[1].name + " 나이: " + students[1].age + " 성적: " + students[1].grade);
}
}
그림으로 흐름 이해
⭐️ 자바에서 대입은 항상 변수에 들어 있는 값을 복사해서 전달한다.
변수에는 인스턴스 자체가 들어있는 것이 아니다! 인스턴스의 위치를 가리키는 참조값이 들어있을 뿐이다. 따라서 대입(=) 시에 인스턴스가 복사되는 것이 아니라 참조값만 복사된다.
배열에 들어있는 객체 사용
배열에 들어있는 객체를 사용하려면 먼저 배열에 접근하고, 그다음에 객체에 접근하면 된다.
학생 1 예제
System.out.println(students[0].name); //배열 접근 시작
System.out.println(x005[0].name); //[0]를 사용해서 x005 배열의 0번 요소에 접근
System.out.println(x001.name); //.(dot)을 사용해서 참조값으로 객체에 접근
System.out.println("학생1");
학생 2 예제
System.out.println(students[1].name); //배열 접근 시작
System.out.println(x005[1].name); //[1]를 사용해서 x005 배열의 1번 요소에 접근
System.out.println(x002.name); //.(dot)을 사용해서 참조값으로 객체에 접근
System.out.println("학생2");
인프런에서 진행한 김영한 님의 강의(김영한의 실전 자바 - 기본편)를 토대로 정리한 포스팅입니다.
자세한 내용은 링크를 참고하시기 바랍니다. 문제시 바로 삭제하겠습니다.