8 분 소요



[김영한의 실전 자바 - 기본편↗️]을 듣고 정리한 글입니다.



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);
    }
}


카테고리:

업데이트:

댓글남기기