실무에서 자주 사용하는 것들 위주로 개념을 다시 다져보려고 한다. 자바로 객체지향 프로그래밍을 하기 위해 가장 우선순위로 중요한 클래스에 대해 다시 학습을 해보기 위해 김영한님의 강의로 진행했다. 이 개념들이 왜 중요한지 문제를 통해 한번 살펴보려고 한다.
문제 : 학생 정보 출력 프로그램 만들기
요구사항
1. 첫 번째 학생의 이름은 "학생1", 나이는 15, 성적은 90입니다.
2. 두 번째 학생의 이름은 "학생2", 나이는 16, 성적은 80입니다.
3. 각 학생의 정보를 다음과 같은 형식으로 출력해야 합니다: "이름: [이름] 나이: [나이] 성적: [성적]"
4. 변수를 사용해서 학생 정보를 저장하고 변수를 사용해서 학생 정보를 출력해야 합니다.
예시 출력
이름: 학생1 나이: 15 성적: 90
이름: 학생2 나이: 16 성적: 80
예시 코드
package class1;
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;
System.out.println("이름:" + student1Name + " 나이:" + student1Age + " 성적:" + student1Grade);
System.out.println("이름:" + student2Name + " 나이:" + student2Age + " 성적:" + student2Grade);
}
}
학생 성적에 대한 정보들을 출력하는 코드를 작성했다. 위 코드처럼 작성할 경우 학생이 늘어나면 늘어나는대로 계속해서 변수와 값을 넣어줘야 하고 출력문도 계속해서 추가를 해줘야 하는 상황이 발생한다.
그러면 계속해서 수정을 해야하고 입력하는 과정에서 오류가 발생하는 상황이 생길 수 있다.
즉 유지보수 및 관리가 어려워 지는 상황이다.
해결방법1 - 배열 사용
package class1;
public class ClassStart2 {
public static void main(String[] args) {
String[] studentNames = {"학생1", "학생2"};
int[] studentAges = {15, 16};
int[] studentGrades = {90, 80};
for (int i = 0; i < studentNames.length; i++) {
System.out.println("이름:" + studentNames[i] + " 나이:" + studentAges[i] + " 성적:" + studentGrades[i]);
}
}
}
배열을 통해 코드 수정을 줄이는데는 성공했지만 여전히 문제는 남아있다. 코드에 보면 배열로 학생에 대한 정보 데이터들이 들어있는데 값을 수정 해야하는 상황이 생기면 배열의 값을 직접 수정 해야한다.
배열에서 값을 변경할 때 예를 들어서 학생2에 대한 정보를 지우자고 했을 때 학생2에 대한 배열 인덱스들을 지워 줘야한다. 지금은 2명의 학생밖에 없기 때문에 손쉽게 지울 수 있지만 1000명의 학생 데이터가 있다고 예를 들었을 때 257번째 학생의 인덱스를 지워야 한다 했을 때 과연 studentNames배열, studentAges배열, studentGrade배열에 있는 257번째 학생의 인덱스를 정확하게 잘 지울 수 있을까?
1000명 중에 257번째 학생의 인덱스를 찾는거부터 일이 되고 그 데이터가 맞는지도 확인해야 되는 등 많은 시간이 낭비된다. 제대로 지우면 그나마 다행인데 잘못 지웠다가는 문제가 커질 수도 있다.
해결방안2 - 클래스 사용
package class1;
public class Student {
String name;
int age;
int grade;
}
학생에 대한 개념을 묶어서 정의하기 위해 class 키워드를 이용해서 Student를 생성한다. 그리고 학생에 대한 정보 항목(또는 필드)들을 class안에서 생성 해준다.
이름 - String name
나이 - int age
성적 - int grade
자바에서 클래스 안에 선언된 변수들을 보통 멤버 변수(Member Variable) 또는 필드라고 한다.
멤버 변수 : 특정 클래스 안에 선언된 변수들을 말한다.
필드 : 보통 데이터 항목을 가리킬 때 사용하는 용어이다. 흔히 엑셀이나 데이터베이스 등에서 데이터의 각각의 항목을 필드라고 한다.
package class1;
public class ClassStart3 {
public static void main(String[] args) {
Student student1;
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);
}
}
생성된 특정 클래스를 가져다가 사용해서 학생 정보 출력 프로그램을 만들었다.
바로 위 소스를 가지고 간략하게 해석하면 학생(Student) 클래스를 가지고 학생1(student1), 학생2(student2) 객체 또는 인스턴스를 만든 것이다.
소스분석
Student student1
student1 = new Student();
stduent1 = x001;
참조 값을 보관해야 하는 이유
객체를 생성하는 new Student() 코드 자체에는 아무런 이름이 없다. 이 코드는 단순히 Student 클래스를 기반으로 메모리에 실제 객체를 만드는 것이다. 따라서 생성한 객체에 접근할 수 있는 방법이 필요하다. 이런 이유로 객체를 생성할 때 반환되는 참조 값을 어딘가에 보관해두어야 한다. 앞서 Student studet1 변수에 참조 값을 저장해두었으므로 저장한 참조 값을 가지고 실제 메모리에 존재하는 객체에 접근할 수 있다. 단순히 객체를 생성하기 위한 코드이므로 객체를 생성해서 가져다가 사용하기 위해서는 연결고리가 필요하다. 그래서 생성된 객체에 참조 값(주소 값)을 보관한다. 주소 값이라고도 표현하는데 우리가 사는 집 주소를 생각하면 좀 더 이해하기 쉬울꺼라 생각이 든다. 친구 집을 찾아가기 위해 집 주소를 알아야되는 것처럼 해당 객체를 사용하기 위해서 해당 객체가 보관하고 있는 주소 값으로 찾아가 사용을 하는 것이다.
코드분석을 간단하게 풀어보면
Student student1 = new Student() // 1. 객체 생성
Student student1 = x001 // 2. new Student()의 결과로 x001 참조 값 반환
student1 = x001 // 3. 최종 결과
학생2(student2)까지 생성하면 아래와 같이 Student 객체가 메모리에 2개 생성된다. 각각 객체의 참조 값이 다르기 때문에 구분이 가능하다.
다른 것을 확인하고 싶으면 아래 코드로 확인을 해보면 된다.
System.out.println(student1);
System.out.println(student2);
참고