실무에 필요한 객체지향의 핵심 개념 제대로 이해하는 게 목표!
새로운 프로젝트를 생성한다.

Main 파일을 실행한다.

자바 세상은 클래스와 객체로 이루어져 있다. 클래스와 객체라는 개념이 왜 필요한지 부터, 클래스가 어떤 방식으로 발전하면서 만들어졌는지 점진적으로 알아보겠다.
package class1;
public class ClassStart1 {
public static void main(String[] args) {
String stu1Name = "stu1";
int stu1Age = 15;
int stu1Grade = 90;
String stu2Name = "stu2";
int stu2Age = 16;
int stu2Grade = 80;
System.out.println("name : " + stu1Name + " age : " + stu1Age + " grade : " + stu1Grade);
System.out.println("name : " + stu2Name + " age : " + stu2Age + " grade : " + stu2Grade);
}
}
이 코드의 문제는 학생이 늘어날 때 마다 변수를 추가로 선언해야 하고, 또 출력하는 코드도 추가해야 한다. 배열을 사용하면 문제를 해결할 수 있다.
package class1;
public class ClassStart2 {
public static void main(String[] args) {
String[] studentNames = {"stu1", "stu2"};
int[] studentAges = {15, 16};
int[] studentGrades = {90, 80};
for (int i = 0; i < studentNames.length; i++) {
System.out.println("name : " + studentNames[i] + " age : " + studentAges[i] + " grade : " + studentGrades[i]);
}
}
}
배열을 사용해서 코드 변경을 최소화하는데는 성공했지만, 한 학생의 데이터가 studentNames[] , studentAges[] , studentGrades[] 라는 3개의 배열에 나누어져 있기 때문에 데이터를 변경할 때 매우 조심해서 작업해야 한다. 예를 들어서 학생 2의 데이터를 제거하려면 각각의 배열마다 학생2의 데이터를 정확하게 찾아서 제거 해야 한다.
이름, 나이, 성적을 각각 따로 나누어서 관리하는 것은 사람이 관리하기 좋은 방식이 아니다.
사람이 관리하기 좋은 방식은 학생이라는 개념을 하나로 묶는 것이다. 그리고 각각의 학생 별로 본인의 이름, 나이, 성적 을 관리하는 것이다.
클래스를 사용해서 학생이라는 개념을 만들고, 각각의 학생 별로 본인의 이름, 나이, 성적을 관리하려고 한다.
package class1;
public class Student {
String name;
int age;
int grade;
}
class 키워드를 사용해서 학생 클래스( Student )를 정의한다. 학생 클래스는 내부에 이름( name ), 나이( age ), 성 적( grade ) 변수를 가진다.
이렇게 클래스에 정의한 변수들을 멤버 변수, 또는 필드라 한다.
클래스는 관례상 대문자로 시작!(낙타표기법 사용)
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("name : " + student1.name + " age : " + student1.age + " grade : " + student1.grade);
System.out.println("name : " + student2.name + " age : " + student2.age + " grade : " + student2.grade);
}
}
int, string과 같은 타입을 직접 만들 수 있다. 클래스는 설계도이고, 이 설계도를 기반으로 실제 메모리에 만들어진 실체를 객체 또는 인스턴스라고 한다.(객체 = 인스턴스)
Student student1 : Student 타입을 받을 수 있는 변수를 선언한다. 
student1 = new Student()
new Student()는 Student 클래스 정보를 기반으로 새로운 객체를 생성하라는 뜻이다. new 클래스명()을 사용하면 된다. 마지막에 () 추가!!
new 키워드를 통해 객체를 생성하면 메모리 어딘가에 있는 객체에 접근 가능한 참조값(주소)를 반환한다. Student student1 변수는 메모리에 조ㄴ재하는 실제 Student 객체(인스턴스)의 참조값을 가지고 있다. 객체를 생성하는 new Student() 코드 자체에는 아무런 이름이 없다. 이 코드는 단순히 Student 클래스를 기반으로 메모리에 실제 객체를 만드는 것이다. 따라서 객ㅊ에 접근할 수 있는 방법이 필요하다. Student student1 변수에 참조값(x001)을 저장해두었으므로 저장한 참조값을 통해서 실제 메몰ㅣ에 조ㄴ재하는 객체에 접근할 숭 ㅣㅆ다.
Student student1 = new Student(); //1. Student 객체 생성
Student student1 = x001; //2. new Student()의 결과로 x001 참조값 반환
student1 = x001; //3. 최종 결과
System.out.println(student1);
System.out.println(student2);
출력해보면 알 수 있다.
. 키워드를 통해 참조값을 사용해서 객체에 접근한다.
객체를 생성하기 위한 '틀' 또는 '설계도'이다. 객체가 가져야 할 소성(변수)과 기능(메서드)를 정의한다.
객체는 클래스에서 정의한 속성과 기능을 가진 실체이다. 객체는 서로 독립적인 상태를 가진다.
인스턴스는 특정 클래스로부터 생성된 객체를 의미한다. 객체와 혼용된다.
둘다 클래스에서 나오는 실체라는 의미에서 비슷하게 사용되지만, 용어상 인스턴스는 객체보다 좀 더 관계에 초점을 맞춘 단어이다.
모든 인스턴스는 객체이지만, 우리가 인스턴스라고 부르는 순간은 특정 클래스로부터 그 객체가 생성되었음을 강조하고 싶을 때이다.

변수에는 인스턴스 위치 가리키는, 인스턴스에 접근할 수 있는 참조값만 있을 뿐이다.
대입(=)시에 인스턴스가 복사 되는 게 아니라 참조값만 복사된다.
자바에서 대입은 항상 변수에 들어있는 값을 복사에서 전달한다.
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");
출력에서 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문 적용
for (int i = 0; i < students.length; i++) {
System.oust.println("이름: " + students[i].name + " 나이 : ". students[i].age + " 성적 : ". students[i].grade);
}
}
}
직접 정의한 Student 타입도 일반적인 변수와 동일하게 배열을 생성할 때 포함할 수 있다.
Student[] students = new Student[] {student1, student2};
생성과 선선을 동시에 하는 경우 다음과 같이 더 최적화 할 수 있다.
Student[] students = {student1, student2};
배열을 사용한 덕분에 for문을 사용해서 반복 작업을 깔끔하게 처리할 수 있다.
for (int i = 0; i < students.length; i++) {
System.out.println("이름 : " + students[i].name + " 나이 : " + students[i].age + ...);
}
for (int i = 0; i < students.length; i++) {
Student s = students[i];
System.out.println("이름 : " + s.name + " 나이 : " + s.age + ...);
}
다음과 같이 향상된 for문을 사용하는 것이 가장 깔끔하다.
for (Student s : students) {
System.out.println("이름 : " + s.name + " 나이 : " + s.age + " 성적 : " + s.grade);
}