1-1. 클래스가 필요한 이유 (존재 이유)
ClassStart1.java (변수 사용)
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);
}
}
- 문제점 : 학생이 늘어날 때마다 변수를 추가로 선언하고, 출력 코드도 추가해야함.
ClassStart2.java (배열 사용)
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]);
}
}
}
- 코드 변경을 최소화 했지만, 한 학생의 데이터가 3개의 배열로 나뉘어 있다. ( studentNames[ ] , studentAges[ ] , studentGrades[ ] )
=> 데이터 변경시 조심해야 함. (실수할 가능성이 높다) - 컴퓨터 입장에서는 상관없지만, 사람이 관리하기에 어려운 방식이다
=> 학생이라는 개념을 하나로 묶어 각각의 학생별로 이름, 나이, 성적을 관리하는 것이 좋음
1-2. 클래스 도입
클래스를 사용해 학생이라는 개념 생성, 각각의 학생 별로 이름, 나이, 성적을 관리
Student.java (클래스)
package class1;
public class Student {
String name;
int age;
int grade;
}
클래스에 정의한 변수들을 멤버 변수, 또는 필드라고 함 => name, age, grade
- 멤버 변수(Member Variable) : 특정 클래스에 소속된 멤버이기 때문에 멤버 변수라고 함.
- 필드(Field) : 데이터 항목을 가르키는 전통적인 용어. 데이터베이스, 엑셀 등에서 데이터 각각의 항목을 필드라고 함.
- 자바에서는 두 가지가 같은 뜻
- 클래스는 대문자로 시작, 낙타 표기법 사용
ClassStart3.java (클래스 사용)
package class1;
public class ClassStart3 {
public static void main(String[] args) {
Student student1;
student1 = new Student(); // new Student()로 학생을 실제 메모리에 만듦 => 인스턴스(객체)
student1.name = "학생1";
student1.age = 15;
student1.grade = 90;
Student student2;
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 )이라는 타입을 만들면 되지 않을까? => 클래스를 사용
- 사용자가 직접 정의하는 사용자 정의 타입을 만들려면 설계도가 필요하다. 이 설계도가 바로 클래스이다.
- 설계도인 클래스를 사용해서 실제 메모리에 만들어진 실체를 객체 또는 인스턴스라 한다.
- 클래스를 통해서 사용자가 원하는 종류의 데이터 타입을 마음껏 정의할 수 있다.
클래스 => 설계도 (붕어빵 틀)
객체, 인스턴스 => 설계도를 기반으로 실제 메모리에 만들어진 실체 (붕어빵, 팥붕, 슈붕)
위 코드를 하나씩 분석,
1. 변수 선언
- Student 타입을 받을 수 있는 변수를 선언
- int는 정수를, String은 문자를 담을 수 있듯, Student는 Student 타입의 객체(인스턴스)를 받을 수 있다.
2. 객체 생성
- 객체를 사용하려면 먼저 설계도인 클래스를 기반으로 객체(인스턴스)를 생성해야 함
객체 생성 =>new 클래스명(), 괄호 필수 - new Student() : Student 클래스 정보를 기반으로 새로운 객체를 생성하라는 뜻. new는 새로 생성한다는 뜻.
=> 메모리에 실제 Student 객체(인스턴스)를 생성 - Student 클래스가 가진 String name, int age, int grade 멤버변수를 사용하는데 필요한 메모리 공간도 함께 확보
3. 참조값 보관
- 객체를 생성하면 자바는 메모리 어딘가에 있는 이 객체에 접근할 수 있는 참조값(주소)( x001 )을 반환
(실제로 x001 처럼 표현되는 것은 아니고 이해를 돕기 위한 예시) - new 키워드를 통해 객체가 생성되고 나면 참조값을 반환
- 앞서 선언한 변수인 Student student1 에 생성된 객체의 참조값( x001 )을 보관 => student1 = x001
student1 변수를 통해 메모리에 있는 실체 객체에 접근하고 사용할 수 있음
참조값을 변수에 보관해야 하는 이유
객체를 생성하는 new Student() 코드는 단순히 Student 클래스를 기반으로 메모리에 실제 객체를 만드는 것.
따라서 생성한 객체에 접근할 수 있는 방법이 필요하기에, 객체를 생성할 때 반환되는 참조값을 어딘가에 보관해야 함.
앞서 Student student1 변수에 저장한 참조값( x001 )을 통해서 실제 메모리에 존재하는 객체에 접근 가능.
학생2(student2)를 생성하면 Student 객체(인스턴스)가 메모리에 2개 생성된다. 각각 참조값이 달라 구분 가능하다.
System.out.println(student1);
System.out.println(student2);
@ 앞은 패키지 + 클래스 정보
@ 뒤의 16진수는 참조값
1-3. 객체 사용
클래스를 통해 생성한 객체를 사용하려면, 먼저 메모리에 존재하는 객체에 접근해야 함.
객체 접근은 .(점, dot)을 사용
객체에 값 대입
// 1. student1 객체의 name 멤버 변수에 값 대입
student1.name="학생1"
// 2.변수에 있는 참조값을 통해 실제 객체에 접근, 해당 객체의 name 멤버 변수에 값 대입
x001.name="학생1"
객체가 가지고 있는 멤버 변수( name , age , grade )에 값을 대입하려면,
. (점, dot) 키워드를 사용해 객체에 접근하면 된다.
=> 이 키워드(.)는 변수( student1 )에 들어있는 참조값( x001 )을 읽어서 메모리에 존재하는 객체에 접근한다.
ex) student1. (dot)이라고 하면 student1 변수가 가지고 있는 참조값을 통해 실제 객체에 접근한다.
객체 값 읽기
// 1. 객체 값 읽기
System.out.println("이름:" + student1.name);
// 2. 변수에 있는 참조값을 통해 실제 객체에 접근하고, name 멤버 변수에 접근한다.
System.out.println("이름:" + x001.name);
// 3. 객체의 멤버 변수의 값을 읽어옴
System.out.println("이름:" + "학생1");
. (점, dot) 키워드를 통해 참조값을 사용해서 객체에 접근한 다음에 원하는 작업을 하면 된다.
1-4. 클래스, 객체, 인스턴스 정리
클래스 - Class
클래스는 객체를 생성하기 위한 '틀' 또는 '설계도'
클래스는 객체가 가져야 할 속성(변수)과 기능(메서드)를 정의
객체 - Object
객체는 클래스에서 정의한 속성과 기능을 가진 실체
객체는 서로 독립적인 상태 => student1 과 student2 는 같은 클래스에서 만들어졌지만, 서로 다른 객체
인스턴스 - Instance
인스턴스는 특정 클래스로부터 생성된 객체를 의미 (그래서 객체와 인스턴스라는 용어는 자주 혼용)
인스턴스는 주로 객체가 어떤 클래스에 속해 있는지 강조할 때 사용
=> student1 객체는 Student 클래스의 인스턴스다
객체 vs 인스턴스
클래스에서 나온 실체라는 의미에서 비슷하게 사용되지만,
용어상 인스턴스는 객체보다 좀 더 관계에 초점을 맞춘 단어이다.
하지만 둘다 클래스에서 나온 실체라는 핵심 의미는 같기 때문에 보통 둘을 구분하지 않고 사용한다.
1-5. 배열 도입 - 시작
새로운 학생이 추가될 때 마다 출력하는 부분이 함께 추가 되어야하는 번거로움이 있다.
배열을 사용해 특정 타입을 연속한 데이터 구족로 묶어 편하게 관리 가능.
ClassStart4.java (배열 도입)
package class1;
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]; // null로 초기화 되어 있음
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);
}
}
- Student 클래스 기반을 student1, student2 인스턴스를 생성하고, 값을 대입한다.
- Student를 담을 수 있는 배열을 생성하고 해당 배열에 student1, student2 인스턴스를 보관한다.
- 자바에서 대입은 항상 변수에 들어 있는 값을 복사한다. ex) students[0] = student1; => students[0] = x001;
- 이제 배열은 x001 , x002 의 참조값을 가진다.
- 변수에는 인스턴스 자체가 들어있는 것이 아니다! 인스턴스의 위치를 가리키는 참조값이 들어있을 뿐이다!
따라서 대입 ( = )시에 인스턴스가 복사되는 것이 아니라 참조값만 복사된다
배열에 들어있는 객체 사용
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-6. 배열 도입 - 리펙토링
ClassStart5.java (for문 도입)
package class1;
public class ClassStart5 {
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[]{student1, student2};
for (int i = 0; i < students.length; i++) {
System.out.println("이름:" + students[i].name + " 나이:" + students[i].age + " 성적:" + students[i].grade);
}
}
}
배열 선언 최적화
Student[] students = new Student[]{student1, student2};
Student[] students = {student1, student2}; // 배열 선언 최적화
for문 최적화
// 반복 요소를 변수에 담아서 처리
for (int i = 0; i < students.length; i++) {
Student s = students[i]; // 축약
System.out.println("이름:" + s.name + " 나이:" + s.age + ...);
}
// 향상된 for문(Enhanced For Loop)
for (Student s : students) {
System.out.println("이름:" + s.name + " 나이:" + s.age + " 성적:" + s.grade);
}
1-7. 문제와 풀이
MovieReviewMain.java
package class1.ex;
public class MovieReviewMain {
public static void main(String[] args) {
MovieReview movieReview1 = new MovieReview(); // 객체 명 예시: inception
movieReview1.title = "인셉션";
movieReview1.review = "인생은 무한 루프";
MovieReview movieReview2 = new MovieReview(); // 객체 명 예시: aboutTime
movieReview2.title = "어바웃 타임";
movieReview2.review = "인생 시간 영화!";
MovieReview[] movieReviews = {movieReview1, movieReview2};
for (MovieReview m : movieReviews) {
System.out.println("영화 제목: " + m.title + ", 리뷰: " + m.review);
}
}
}
ProductOrderMain.java
package class1.ex;
public class ProductOrderMain {
public static void main(String[] args) {
ProductOrder tofu = new ProductOrder();
tofu.productName = "두부";
tofu.price = 2000;
tofu.quantity = 2;
ProductOrder kimchi = new ProductOrder();
kimchi.productName = "김치";
kimchi.price = 5000;
kimchi.quantity = 1;
ProductOrder cock = new ProductOrder();
cock.productName = "콜라";
cock.price = 1500;
cock.quantity = 2;
ProductOrder[] orders = {tofu, kimchi, cock};
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);
}
}