[Java] 김영한의 실전 자바 기본편 - #1 클래스와 데이터
[김영한의 실전 자바 - 기본편↗️]을 듣고 정리한 글입니다.
1. 클래스와 데이터
1.1 클래스가 필요한 이유
먼저 클래스가 왜 필요한지 아래 코드를 통해 이해해보자.
- 문제: 학생 정보 출력 프로그램 만들기
- 두 명의 학생 정보를 출력하는 프로그램을 작성해야 한다. 각 학생은 이름, 나이, 성적을 가지고 있다.
-
① 변수 사용
-
학생이 늘어날 때 마다 변수를 추가로 선언해야 하고, 또 출력하는 코드도 추가해야 하는 문제가 있다.
public class Main { 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); } }
-
-
② 배열 사용
- 한 학생의 데이터가
studentNames[ ]
,studentAges[ ]
,studentGrades[ ]
3개의 배열에 나누어져 있기 때문에 데이터를 변경할 때 매우 조심해서 작업해야한다. - 한 학생의 데이터를 관리하기 위해서는 3개의 배열의 인덱스 순서를 항상 정확하게 맞춰야 하는데, 이렇게 하면 특정 학생의 데이터를 변경할 때 실수할 가능성이 매우 높다.
public class Main { 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]); } } }
- 한 학생의 데이터가
➡️ 즉, 사람이 관리하게 좋게 하려면 학생이라는 개념을 하나로 묶은 후에 각각의 학생 별로 본인의 이름, 나이, 성적을 관리하는 것이 좋다.
1.2 클래스와 객체
앞서 이야기한 문제를 클래스를 도입해서 해결해보자.
- 클래스를 사용해서 학생이라는 개념을 만들고, 각각의 학생 별로 본인의 이름, 나이, 성적을 관리해보자.
- 생성한 패키지에
Student
라는 클래스를 생성하자. - 💡 클래스는 관례상 대문자로 시작하고 Camel Case를 사용한다. (변수는 소문자로 시작)
public class Student{
String name;
ing age;
int grade;
}
class
키워드를 사용하여 학생 클래스Student
를 정의한다.- 즉, 클래스를 사용하여
int
,String
과 같은 사용자 정의 타입인Student
타입을 정의한 것이다. - 이렇게 정의한 타입을 사용해서 실제 메모리에 만들어진 실체를 객체 또는 인스턴스라고 한다. (뒤에서 학습)
- 즉, 클래스를 사용하여
- 클래스에 정의한 변수(
name
,age
,grade
)들을 멤버 변수, 또는 필드라고 한다.- 멤버 변수: 이 변수들은 특정 클래스에 소속된 멤버이기 때문에 이렇게 부른다.
- 필드: 데이터 항목을 가리키는 전통적인 용어이다. 데이터베이스, 엑셀 등에서 데이터 각각의 항목을 필드라고 한다.
- 자바에서 멤버 변수, 필드는 같은 뜻이다. 클래스에 소속된 변수를 뜻한다.
이제 학생 클래스를 사용하는 코드를 작성해보자.
package class1;
public class ClassStart {
public static void main(String[] args) {
Student student1 = new Student(); // 1. 변수 선언 및 객체(인스턴스) 생성
student1.name = "학생1"; // 2. Student 인스턴스 참조 값 보관 (ex: student1= x001)
student1.grade = 90;
Student student2 = new Student();
student2.name = "학생1";
student2.grade = 90;
// 3. new Student()의 결과로 생성된 참조 값 확인
System.out.println("student1의 주소: " + student1); // ex: x001
System.out.println("student2의 주소: " + student2); // ex: x002
// 4. 참조 값을 변수에 저장하여 객체에 접근(참조)
System.out.println("이름:" + student1.name + " 나이:" + student1.age + " 성적:" + student1.grade);
System.out.println("이름:" + student2.name + " 나이:" + student2.age + " 성적:" + student2.grade);
}
}
Student student1 = new Student(); // 1. Student 객체 생성
Student student1 = x001; //2. new Student()의 결과로 x001 참조값 반환
student1 = x001; //3. 최종 결과
- 객체를 생성하면 자바는 메모리 어딘가에 있는 이 객체에 접근할 수 있는 참조 값(주소)(
x001
)을 반환한다.- 실제로
x001
처럼 표현되는 것은 아니며, 예시일 뿐이다.
- 실제로
new
키워드를 통해 객체가 생성되고 나면 참조값을 반환한다. 앞서 선언한 변수인Student student1
에 생성된 객체의 참조값(x001
)을 보관한다.Student student1
변수는 이제 메모리에 존재하는 실제Student
객체(인스턴스)의 참조값을 가지고 있다.
객체 접근 후 값 대입
- 객체가 가지고 있는 멤버 변수(
name
,age
,grade
)에 값을 대입하려면 먼저 객체에 접근해야한다. student1.
은student1
변수가 가지고 있는 참조값(ex:x001
)을 읽어x001
위치에 있는 실제 객체(Student
)에 접근한다.
student1.name="학생1" //1. student1 객체의 name 멤버 변수에 값 대입
x001.name="학생1" //2.변수에 있는 참조값을 통해 실제 객체에 접근, 해당 객체의 name 멤버 변수에 값
대입
위 코드에서
new Student()
를 통해Student
객체(인스턴스)가 메모리에 2개 생성되는데, 이 때 각각 객체(인스턴스)는 참조 값이 다르므로 서로 구분이 가능하다.
1.3 클래스, 객체, 인스턴스
위 코드에서
Student
라는 클래스를 기반으로student1
,student2
객체(인스턴스)를 생성하였다.
- 클래스: 클래스는 객체를 생성하기 위한 ‘설계도’이다.
- 객체: 설계도를 기반으로 실제 메모리에 만들어진 실체이며 서로 독립적인 상태를 가진다.
- 인스턴스: 특정 클래스로부터 생성된 객체를 의미하기 때문에 객체와 인스턴스라는 용어는 자주 혼용해서 사용한다.
위 용어를 붕어빵 틀에 비유해보자.
개념 | 비유 | 설명 |
---|---|---|
클래스(Class) | 붕어빵 틀 | 붕어빵의 모양, 크기, 재료 등을 정의하는 설계도. 객체의 속성(크기, 모양, 재료)과 행동(굽는 방법)을 정의. |
객체(Object) | 붕어빵 | 붕어빵 틀로 만든 실제 붕어빵. 같은 틀에서 나왔지만 재료(팥, 슈크림 등)에 따라 다를 수 있음. |
인스턴스(Instance) | 특정한 붕어빵 | 붕어빵 틀로 만들어진 구체적인 붕어빵 하나. 예: 팥이 들어간 붕어빵, 슈크림이 들어간 붕어빵. |
- 즉, 객체를 만들 때마다 새로 정의하는 것이 아니고, 기존에 객체의 형태를 미리 정의해 놓은 클래스를 사용하는 것이다.
- 클래스에서 객체가 생성되는 것을 실체화 라고 하며, 구체적으로 생성된 객체를 인스턴스라고 한다.(일반적으로 인스턴스와 객체를 혼용하기도 함)
1.4 배열 도입
배열을 사용하면 특정 타입을 연속한 데이터 구조로 묶어서 편리하게 관리할 수 있다.
Student
클래스를 사용한 변수들도Student
타입이기 때문에 학생도 배열을 사용해서 하나의 데이터 구조로 묶어서 관리할 수 있다.Student
타입을 사용하는 배열을 도입해보자.
package class1;
public class ClassStart {
public static void main(String[] args) {
Student student1 = new Student();
student1.name = "학생1";
student1.age = 15;
student1.grade = 90;
Student student2 = new Student();
student2 = new Student();
student2.name = "학생1";
student2.age = 16;
student2.grade = 90;
// 배열 선언
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);
}
}
- ⭐ 자바에서 대입은 항상 변수에 들어 있는 값을복사해서 전달한다.
//자바에서 대입은 항상 변수에 들어 있는 값을 복사한다. students[0] = x001; students[1] = x002;
student1
,student2
에는 참조값이 보관되어 있다. 따라서 이 참조값이 배열에 저장되므로student1
,student2
에 들어 있던 참조 값은 당연히 그대로 유지된다.
- ⚠️ 변수에는 인스턴스 자체가 들어있는 것이 아니다! 인스턴스의 위치를 가리키는 참조 값이 들어있을 뿐이므로 대입(
=
)시에 인스턴스가 복사되는 것이 아니라 참조 값만 복사된다.
배열에 들어있는 객체 사용
배열에 들어있는 객체를 사용하려면 먼저 배열에 접근하고, 그 다음에 객체에 접근하면 된다.
// 학생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");
1.5 배열 도입 - 리펙토링
배열을 사용한 덕분에 출력에서 다음과 같이 for문을 도입할 수 있게 되었다.
package class1;
public class ClassStart {
public static void main(String[] args) {
Student student1 = new Student();
student1.name = "학생1";
student1.age = 15;
student1.grade = 90;
Student student2 = new Student();
student2 = new Student();
student2.name = "학생2";
student2.age = 16;
student2.grade = 90;
// 배열 선언
Student[] students = new Student[2];
students[0] = student1;
students[1] = student2;
//for문 적용
for (int i = 0; i < students.length; i++) {
System.out.println("이름: " + students[i].name + " 나이: " + students[i].age + " 성적: " + students[i].grade);
}
}
}
배열 선언 최적화
우리가 직접 정의한 Student
타입도 일반적인 변수와 동일하게 배열을 생성할 때 포함할 수 있다.
// Student[] students = new Student[] {student1, student2}; or
Student[] students = {student1, student2};
for문 최적화
배열을 사용한 덕분에 for문을 사용해서 반복 작업을 깔끔하게 처리할 수 있다.
for (int i = 0; i < students.length; i++) {
System.out.println("이름:" + students[i].name + " 나이:" + students[i].age
+ ...);
for-each
문을 사용해보자. students[i].name
, students[i].age
처럼 students[i]
를 자주 접근하는 것이 번거롭다면 반복해서 사용하는 객체를 Student s
와 같은 변수에 담아두고 사용해도 된다.
(단축키: iter
)
for (Student s : students) {
System.out.println("이름: " + s.name + " 나이: " + s.age + " 성적: " + s.grade);
}
2. 문제와 풀이
2.1 영화 리뷰 관리하기(1)
문제 설명
- 당신은 영화 리뷰 정보를 관리하려고 한다.
- 먼저, 영화 리뷰 정보를 담을 수 있는
MovieReview
클래스를 만들어보자.
요구 사항
MovieReview
클래스는 다음과 같은 멤버 변수를 포함해야 한다.- 영화 제목 (title)
- 리뷰 내용 (review)
MovieReviewMain
클래스 안에main()
메서드를 포함하여, 영화 리뷰 정보를 선언하고 출력하자.
예시 코드 구조
public class MovieReview {
String title;
String review;
}
public class MovieReviewMain {
public static void main(String[] args) {
// 영화 리뷰 정보 선언
// 영화 리뷰 정보 출력
}
}
출력 예시
영화 제목: 인셉션, 리뷰: 인생은 무한 루프
영화 제목: 어바웃 타임, 리뷰: 인생 시간 영화!
내 풀이
package class1.ex;
public class MovieReview {
String title;
String review;
}
package class1.ex;
public class MovieReviewMain1 {
public static void main(String[] args) {
MovieReview inception = new MovieReview();
inception.title = "인셉션";
inception.review = "인생은 무한 루프";
MovieReview aboutTime = new MovieReview();
aboutTime.title = "어바웃 타임";
aboutTime.review = "인생 시간 영화!";
System.out.println("영화 제목: " + inception.title + ", 리뷰: " + inception.review);
System.out.println("영화 제목: " + aboutTime.title + ", 리뷰: " + aboutTime.review);
}
}
2.2 영화 리뷰 관리하기(2)
문제 설명
기존 문제에 배열을 도입하고, 영화 리뷰를 배열에 관리하자.
요구 사항
리뷰를 출력할 때 배열과 for
문을 사용해서 System.out.println
을 한 번만 사용하자.
내 풀이
package class1.ex;
public class MovieReviewMain2 {
public static void main(String[] args) {
MovieReview inception = new MovieReview();
inception.title = "인셉션";
inception.review = "인생은 무한 루프";
MovieReview aboutTime = new MovieReview();
aboutTime.title = "어바웃 타임";
aboutTime.review = "인생 시간 영화!";
MovieReview[] movieReviews = {inception, aboutTime};
for (MovieReview movieReview : movieReviews) {
System.out.println("영화 제목: " + movieReview.title + ", 리뷰: " + movieReview.review);
}
}
}
2.3 상품 주문 시스템 개발
문제 설명
- 당신은 온라인 상점의 주문 관리 시스템을 만들려고 한다.
- 먼저, 상품 주문 정보를 담을 수 있는
ProductOrder
클래스를 만들어보자.
요구 사항
ProductOrder
클래스는 다음과 같은 멤버 변수를 포함해야 한다.- 상품명 (productName)
- 가격 (price)
- 주문 수량 (quantity)
ProductOrder
클래스 안에main()
메서드를 포함하여, 여러 상품의 주문 정보를 배열로 관리하고, 그 정보들을 출력하고, 최종 결제 금액을 계산하여 출력하자.- 출력 예시와 같도록 출력하면 된다.
예시 코드 구조
public class ProductOrder {
String productName;
int price;
int quantity;
}
public class ProductOrderMain {
public static void main(String[] args) {
// 여러 상품의 주문 정보를 담는 배열 생성
// 상품 주문 정보를 `ProductOrder` 타입의 변수로 받아 저장
// 상품 주문 정보와 최종 금액 출력
}
}
출력 예시
상품명: 두부, 가격: 2000, 수량: 2
상품명: 김치, 가격: 5000, 수량: 1
상품명: 콜라, 가격: 1500, 수량: 2
총 결제 금액: 12000
내 풀이
package class1.ex;
public class ProductOrderMain {
public static void main(String[] args) {
ProductOrder order1 = new ProductOrder();
order1.productName = "두부";
order1.price = 2000;
order1.quantity = 2;
ProductOrder order2 = new ProductOrder();
order2.productName = "김치";
order2.price = 5000;
order2.quantity = 1;
ProductOrder order3 = new ProductOrder();
order3.productName = "콜라";
order3.price = 1500;
order3.quantity = 2;
ProductOrder[] orders = {order1, order2, order3};
int total = 0;
for (ProductOrder order : orders) {
System.out.println("상품명: " + order.productName + ", 가격: " + order.price + ", 수량: " + order.quantity);
total += order.price * order.quantity;
}
System.out.println("총 결제 금액: " + total);
}
}
댓글남기기