[Java] 클래스와 데이터

szlee·2023년 12월 4일
0

Java

목록 보기
10/23

< 김영한의 실전 자바 - 기본편 > 강의를 보고 이해한 내용을 바탕으로 합니다.





클래스가 필요한 이유


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

위 코드에서 학생 두명을 다루어야 하므로 각각 다른 변수를 사용했는데,
여기서의 문제점은 학생이 늘어날 때마다 변수를 추가로 선언해야 하고 출력하는 코드도 추가해주어야 한다는 점이다. --> 번거롭다!



그렇다면 해결방법은?
같은 데이터 타입을 하나로 묶을 수 있는 배열을 사용한다.


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

배열 사용의 한계?

배열을 사용해서 코드 변경을 최소화할 수 있었지만,
한 학생의 데이터가 studentNames[], studentAges[], studentGrades[]라는 세개의 배열에 나누어져 있다.
한 학생의 데이터가 세개의 배열에 나누어져 있기 때문에 이 세개의 배열을 각각 변경해야하고, 데이터를 변경할 때 매우 조심해서 작업해야 한다.
그리고 이 때 특정 학생의 데이터를 변경할 때 실수할 가능성이 매우 높다.
--> 사람이 관리하기에 좋은 코드가 ❌
ex) 학생2의 데이터를 변경하려면 각각의 배열마다 학생2의 요소를 정확하게 찾아서 변경해주어야한다.

사람이 관리하기 좋은 방식은 뭘까?

학생이라는 개념을 하나로 묶는 것이다.
그리고 각각의 학생 별로 이름, 나이, 성적을 관리하는 것이다.
--> 클래스 도입 🙆🏻‍♀️









클래스 도입하기

class 키워드를 사용해서 학생 클래스(Student)를 정의한다.
학생 클래스는 내부에 이름(name), 나이(age), 성적(grade) 변수를 가진다.
--> 클래스에 정의한 변수 : 멤버 변수 (또는 필드)

멤버 변수

  • 멤버 변수 : 특정 클래스에 소속된 멤버이기 때문에
  • 필드 : 데이터 항목을 가리키는 전통적인 용어.

클래스는 관례상 대문자로 시작하고 낙타 표기법을 사용한다.


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

    }
}

클래스와 사용자 정의 타입

  • 타입은 데이터의 종류나 형태를 나타낸다.
    • int : 정수 타입, String : 문자타입
  • 학생(Student)이라는 타입을 만들면 되지 않을까?
    • 클래스를 사용하면 int, String과 같은 타입을 직접 만들 수 있다.
  • 사용자가 직접 정의하는 사용자 정의 타입을 만들려면 설계도가 필요하다.
    설계도가 바로 클래스!
  • 설계도인 클래스를 사용해서 ⭐️실제 메모리에 만들어진 실체를 객체 또는 인스턴스⭐️라 한다.
    • Student 클래스를 기반으로 student1, student2 객체(인스턴스)를 만들었다.
  • 클래스를 통해서 사용자가 원하는 종류의 데이터 타입을 마음껏 정의할 수 있다.

🌟클래스 => 추상
🌟인스턴스(객체) => 실체(구체)







클래스로 객체를 생성하고 참조값을 담기

1. 변수 선언

Student student1
Student 타입을 받을 수 있는 변수를 선언한다.

2. 객체 생성

student1 = new Student();
객체를 사용하려면 먼저 설계도인 클래스를 기반으로 객체(인스턴스)를 생성해야한다.
이후 메모리에 실제 객체(인스턴스)를 생성한다.
객체를 생성할 때는 new 클래스명()을 사용하면 된다.

Student 클래스는 String name, int age, int grade멤버 변수를 가지고 있다.
이 변수를 사용하는데 필요한 메모리 공간도 함께 확보한다.

3. 참조값 보관

객체를 생성하면 자바는 메모리 어딘가에 있는 이 객체에 접근할 수 있는 참조값(주소)를 반환한다.
new 키워드를 통해 객체가 생성되고 나면 참조값을 반환한다.

Student student1 변수는 이제 메모리에 존재하는 실제 Student 객체(인스턴스)의 참조값을 가지고 있다.
student1 변수는 방금 만든 객체에 접근할 수 있는 참조값을 가지고 있다.
따라서 이 변수를 통해서 객체를 접근(참조)할 수 있다.
즉, student1 변수를 통해 메모리에 있는 실제 객체를 접근하고 사용할 수 있다.

참조값을 변수에 보관해야하는 이유?
객체를 생성하는 new Student() 코드 자체에는 아무런 이름이 있다.
단순히 메모리에 실제 객체를 만드는 것이다.
따라서 생성한 객체에 접근할 수 있는 방법이 필요하다.
-> 객체를 생성할 때 반환되는 참조값을 어딘가에 보관해두어야한다.
🌟즉 변수는, 객체 생성의 결과로 반환되는 참조값을 담을 그릇이었던 것~!🤓

Student student1 = new Student(); //1. Student 객체 생성
Student student1 = x001; //2. new Student()의 결과로 x001 참조값 반환
student1 = x001; //3. 최종 결과

이후에 학생2(student2)도 생성하면 Student 객체가 메모리에 두개 생성된다.
각각 참조값이 다르기 때문에 서로 구분할 수 있다.

System.out.println(student1);
System.out.println(student2);

의 결과를 보니 다음과 같았다.

@ 뒤의 값이 바로 참조값이다.






객체 사용

클래스를 통해 생성한 객체를 사용하려면 먼저 메모리에 존재하는 객체에 접근해야 한다. 이 때 점.을 사용하면 된다.
student1.name = "학생1
위 코드를 실행하면, student1변수가 가지고 있는 참조값을 통해 실제 객체에 접근한 후, name멤버 변수에 '학생1' 데이터가 저장된다.




클래스, 객체, 인스턴스 정리

클래스 : 추상

클래스는 객체를 생성하기 위한 설계도.
클래스는 객체가 가져야할 속성(변수)기능(메서드)를 정의한다.

객체 : 구체

클래스에서 정의한 속성과 기능을 가진 실체.
객체는 서로 독립적인 상태를 가진다.
ex) student1student2는 같은 클래스에서 만들어졌지만 서로 다른 객체이다.

인스턴스

특정 클래스로부터 생성된 객체.
인스턴스는 주로 객체가 어떤 클래스에 속해 있는지를 강조할 때 사용한다. (관계에 초점을 맞춘다.)
ex) student1 객체는 Student 클래스의 인스턴스다.






배열을 도입해서 리팩토링 해보기

학생을 출력하는 부분을 보면 새로운 학생이 추가될 때마다 출력하는 부분도 함께 추가해야 한다.

System.out.println("이름:" + student1.name + " 나이:" + student1.age + " 성적:" + student1.grade);
System.out.println("이름:" + student2.name + " 나이:" + student2.age + " 성적:" + student2.grade);

배열을 사용하면 특정 타입을 연속한 데이터 구조로 묶어서 편리하게 관리할 수 있다.
Student 클래스를 사용한 변수들도 Student 타입이기 때문에 학생도 배열을 사용해서 하나의 데이터 구조로 묶어서 관리할 수 있다.

배열에 참조값 대입

Student를 담을 수 있는 배열을 생성하고, 해당 배열에 student1, student2 인스턴스를 보관한다.
Student[] students = new Student[2];

  • Student 변수를 두개 보관할 수 있는 사이즈 2의 배열을 만든다.
  • Student 타입의 변수는 Student 인스턴스의 참조값을 보관한다.
    • Student 배열의 각각의 항목도 Student 타입의 참조값을 보관한다.
  • 배열에는 아직 참조값을 대입하지 않았으므로 null 값으로 초기화된다.



배열에 객체 보관

student[0] = student1; //x001
student[1] = student2; //x002
//자바에서 대입은 항상 변수에 들어있는 값을 복사한다.

for(Student s: students){
     System.out.println("이름:" + s.name + " 나이:" + s.age + " 성적:" + s.grade);
}

🌟🌟🌟 자바에서 대입은 항상 변수에 들어있는 값을 복사❗️한다!!

student1, student2에는 참조값이 보관되어있다.
따라서 이 참조값이 배열에 저장된다.
(student1, student2에 보관된 참조값을 읽고 복사해서 배열에 대입한다.)

이제 배열은 두 참조값을 모두 가지므로 두 인스턴스 모두에 접근할 수 있다.

자바에서 변수의 대입(=)은 변수에 들어있는 값을 복사해서 전달하는 것이다.
student1, student2에는 참조값이 들어있고, 이 값을 복사해서 배열에 전달한다.
따라서 기존 student1, student2에 들어있던 참조값을 당연히 그대로 유지된다.

변수에는 인스턴스 자체가 들어있는 것이 아니라, 인스턴스의 위치를 가리키는 참조값이 있을 뿐이다.
따라서 ⭐️대입(=)시에 인스턴스가 복사되는 것이 아니라, 참조값만 복사된다.⭐️



배열 속 객체 사용

먼저 배열에 접근하고 그 다음 객체에 접근한다.
System.out.println(students[0].name);

profile
🌱

0개의 댓글