본문 바로가기
전공 수업/객체 지향 프로그래밍(Java)

[10주 차] - 클래스 변수, 인스턴스 변수, 지역 변수, 클래스 메서드와 인스턴스 메서드

by TwoJun 2022. 11. 6.

    과목명 : 객체지향 프로그래밍(Object oriented programming)

수업일자 : 2022년 11월 02일 (수)

 

 

 

 

 

1. 객체 지향 프로그래밍 언어(Object Oriented Programming Language)

1-1. 객체 지향 프로그래밍(Object Oriented Programming, OOP)

- 객체 지향 프로그래밍이란, 절차 지향 프로그래밍(Procedural programming)의 방식을 보완하기 위해 등장하게 된 프로그래밍 패러다임(Programming paradigm) 중 하나로써, 프로그래밍에서 필요한 데이터들을 추상화시킨 뒤 특정한 상태와 행위를 가지는 객체를 만들고 그 객체들 간의 유기적인 상호 작용을 통해 모든 로직을 구성하도록 하는 프로그래밍 기법 중 하나입니다.

 

 

 

 

1-2. 객체 지향 언어의 역사

- 과학, 군사적 모의 실험(Simulation)을 진행하기 위해 컴퓨터를 사용하게 되면서 컴퓨터를 이용하여 가상 세계를 구현하려는 노력으로부터 객체 지향 이론이 시작되었습니다.

 

- 1960년대 최초의 객체 지향 언어인 "Simula"가 탄생했습니다.

 

- 1980년대 절차 방식 프로그래밍의 한계를 객체 지향 프로그래밍 방식으로 극복하고자 노력했으며 이를 통해 C++, Smalltalk과 같은 보다 발전된 객체 지향 프로그래밍 언어가 탄생했습니다.

 

- 1995년 말, Java가 개발되었으며 객체 지향 프로그래밍 언어의 주류가 되었습니다.

 

 

 

 

1-3. 객체 지향 언어의 특징

(1) 기존 프로그래밍 언어와 크게 다르지 않습니다.

- 기존 프로그래밍 언어에 몇 가지 규칙을 추가한 부분입니다.

 

(2) 코드의 재사용성이 높습니다.

- 새로운 코드를 작성할 때 기존의 코드를 이용해서 쉽게 작성할 수 있습니다.

 

(3) 코드의 관리(유지보수)가 쉽습니다.

- 코드 간의 관계를 맺어줌으로써 보다 적은 노력으로 코드 변경이 가능합니다.

 

(4) 신뢰성이 높은 프로그램을 개발할 수 있게 합니다.

- 제어자와 메서드를 이용해서 데이터를 보호하고, 코드의 중복을 제거하여 코드의 불일치로 인한 오류를 방지할 수 있습니다.

 

 

 

 

 

 

2. 클래스(Class)와 객체(Object)

2-1. 클래스의 정의와 용도

(1) 정의

- 클래스란, 객체를 정의할 수 있는 설계도와 같은 의미로 사용됩니다. Java에서는 객체를 생성할 수 있는 설계도인 클래스를 가지고 여러 객체를 생성하여 사용할 수 있습니다.

 

(2) 용도

- 클래스는 객체를 생성하는데 사용됩니다.

 

 

 

 

2-2. 객체의 정의와 용도

(1) 정의 

- 클래스의 인스턴스라고도 부르며 실제 소프트웨어 세계에 구현할 대상입니다.

- 실제로 존재하는 것, 사물 또는 개념이라고도 정의됩니다.

 

(2) 용도

- 객체의 속성과 기능에 따라 모두 다릅니다.

 

 

 

 

2-3. 객체와 인스턴스

(1) 객체(Object)는 인스턴스(Instance)를 포함하는 일반적인 의미입니다.

 

(2) 인스턴스화(Instantiate) : 클래스로부터 인스턴스를 생성하는 것을 의미합니다.

 

 

 

 

2-4. 객체의 구성요소 

(1) 객체는 속성과 기능으로 이루어져 있습니다.

- 객체는 속성과 기능의 집합이며, 속성과 기능을 객체의 멤버(Member, 구성요소)라고 합니다.

 

(2) 속성은 변수로, 기능은 메서드로 정의합니다.

- 클래스를 정의할 때 객체의 속성은 변수로, 기능은 메서드로 정의합니다.

class Car {
    // 차들의 속성(변수로 정의, 차례대로 차의 이름, 색상, 문의 개수)
    String carName;
    String carColor;
    int carDoor;
    
    // 차들의 기능(메서드로 정의, 엔진 시동 On/Off 기능, 기어 조절 기능)
    void engineOnOff() { engineOn = !engineOn; }
    
    void gearType(int gearCount) {
        int gearState = 0;
        gearState = gearCount;
        }  
}

 

 

 

 

 

2-5. 인스턴스의 생성과 사용

(1) 인스턴스 생성 방법

- 문법 : 클래스명.참조변수명 = new 클래스명();

 

- 객체(클래스의 인스턴스)가 생성된다면 생성된 객체의 주소는 선언한 참조변수(Reference variable)에 저장됩니다.

// 객체(클래스의 인스턴스)를 생성하고, 생성된 객체의 주소를 참조변수에 저장합니다.
Car car1 = new Car();    // 생성된 Car의 객체의 주소를 참조변수 car1에 저장

 

 

(2) 인스턴스와 참조변수의 관계

- (a) 하나의 인스턴스를 여러 개의 참조변수가 가리키는 것은 가능합니다.

- (b) 여러 개의 인스턴스를 하나의 참조변수가 가리키는 것은 불가능합니다.

 

 

 

 

 

2-6. 클래스의 또 다른 관점 (정의 - 1)

(1) 변수 : 하나의 데이터를 저장할 수 있는 공간

(2) 배열 : 같은 데이터 타입의 여러 데이터를 저장할 수 있는 공간

(3) 구조체 - 데이터 타입에 관계없이 서로 관련있는 데이터들을 저장할 수 있는 공간

(4) 클래스 - 데이터와 메서드의 결합(구조체 + 메서드)

 

 

 

 

 

2-7. 클래스의 또 다른 관점 (정의 - 2)

(1) 클래스는 사용자 정의 타입(User-defined type)입니다.

-  직접 새로운 타입을 정의할 수 있으며, 서로 관련된 값이나 기능들을 묶어서 하나의 타입으로 정의합니다.

 

 

 

 

 

 

3. 변수(Variable)와 메서드(Method)

3-1. 선언 위치에 따른 변수의 종류

- 변수의 선언 위치가 변수의 종류와 범위(Scope)를 결정합니다.

class VariableType {
    // 인스턴스 변수 
    int instanceVariable;
    
    // 클래스 변수
    static int classVariable;
    
    
    void method() {
        // 지역 변수
        int localVariable = 0;
    }
}

 

 

변수의 종류 선언 위치 생성 시기
클래스 변수(Class variable) 클래스 영역 클래스가 메모리에 적재될 때
인스턴스 변수(Instance variable) 인스턴스가 생성될 때
지역 변수(Local variable) 메서드 영역 변수를 선언할 때 

 

(1) 인스턴스 변수(Instance variable)

- 클래스에서 정의된 변수로 이를 위해 각각 인스턴스화된 클래스의 객체들의 개별적인 저장 공간입니다.

 

- 각 인스턴스마다 다른 값을 저장할 수 있습니다.

 

- 인스턴스를 생성할 때 인스턴스 변수가 생성되고, 참조변수가 없는 경우엔 Garbage collector에 의해 자동으로 제거됩니다.

 

 

 

(2) 클래스 변수(Class variable)

- 동일한 클래스의 모든 인스턴스들이 공유하는 변수입니다.(모든 인스턴스가 공통된 값을 공유)

따라서, 생성된 각 객체(인스턴스)들이 공통적인 값을 가져야 할 때 클래스 변수를 선언합니다.

 

- 인스턴스 생성 없이, "클래스명.클래스 변수명"으로 접근 가능합니다.

 

- 선언 시, 데이터 타입 옆에 static 키워드를 붙입니다.

 

- 클래스가 로딩될 때 생성되고 프로그램이 종료될 때 소멸합니다.

 

 

 

(3) 지역 변수(Local Variable)

- 메서드 내에 선언되며, 메서드의 종료와 함께 소멸합니다.

 

- 조건문, 반복문의 블럭 내에 선언된 지역변수는 블럭을 벗어나는 순간 소멸됩니다.

 

 

 

 

 

3-2. 클래스 변수와 인스턴스 변수의 차이

- 인스턴스 변수는 인스턴스(객체)가 만들어질 때마다 생성되므로  만들어진 각각의 인스턴스(객체)마다 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스(객체)가 하나의 저장 공간을 공유하므로 항상 공통된 값을 가집니다.

 

 

 

 

 

3-3. 메서드(Method)

(1) 정의와 특징

- 특정 작업이나 연산을 수행하기 위한 명령문의 집합입니다.

 

- 특정 값을 파라미터로 전달받아서 작업을 처리하고 그 결과값을 리턴합니다.

 

- 리턴값이 없는 경우 메서드 정의 시 메서드명 옆에 void를 붙입니다.

 

- 메서드는 클래스 영역에서만 정의할  수 있습니다.

- 문법 : 리턴값의 데이터 타입 메서드명(데이터 타입 변수명 1, 데이터 타입 변수명 2, ... 데이터 타입 변수명 n) {

 

                 // 메서드 호출 시 수행할 문장;

 

             }

int numberAdd(int number1, int number2) {
    // 메서드 호출 시 수행문
    int result = number1 + number2;
    
    // 수행 결과값 반환
    return result;
}

 

 

(2) 메서드의 장점

- 반복적인 코드를 줄이고 코드의 유지보수(관리)가 용이해집니다.

 

 

 

(3) 메서드의 작성 방법

- 반복적으로 수행되는 여러 문장을 메서드로 작성합니다.

 

- 하나의 메서드는 한 가지 기능만 수행하도록 작성합니다.

 

- 관련된 여러 문장을 메서드로 작성합니다.

 

 

 

 

 

3-4. return문

(1) 메서드가 정상적으로 종료되는 경우입니다.

- 메서드의 블록{} 끝에 도달한 경우

- 메서드의 수행문 수행 도중, return문을 만났을 때

 

 

(2) return문

- 현재 실행 중인 메서드를 종료하고 메서드를 호출한 지점으로 되돌아갑니다.

- 메서드의 반환값(리턴값)이 없는 경우 : return; 형태로 작성합니다.

- 메서드의 반환값(리턴값)이 있는 경우 : return 반환값; 형태로 작성합니다

 

 

(3)  return문 작성 시 유의 사항

- 반환값이 존재하는 메서드는 모든 경우에 return문이 있어야 합니다.

int maxValue(int num1, int num2) {
    if (num1 > num2) return num1;
    else return num2;
}

 

 

(4) return문을 적절히 사용하면 코드가 간결해질 수 있습니다.

 

 

 

 

 

 

3-5. 메서드의 호출

(1) 메서드 호출

- 문법 : 참조변수명 또는 클래스명.메서드명();                                              

- 문법 : 참조변수명 또는 클래스명.메서드명(전달인자 1, 전달인자 2, ... );     

 

 

 

 

 

3-6. JVM의 대략적인 메모리 구조

(1) Method area (메서드 영역)

- 클래스 정보, 클래스 변수가 저장되는 영역입니다.

 

(2) 호출 스택(Call stack)

- 메서드의 작업 공간으로 메서드가 호출되면 메서드 수행에 필요한 메모리 공간을 할당받고, 메서드가 종료되면 사용한 메모리 공간을 반환하게 됩니다.

 

(3) Heap 영역

- 동적으로 생성된 객체(인스턴스)가 저장되는 공간이며 new 연산자에 의해 생성된 배열과 객체는 모두 여기에 생성됩니다.

대략적인 메모리 구조

 

 

 

 

3-7. JVM의 메모리 구조 - Call Stack(호출 스택)

(1) 메서드가 호출되면 수행에 필요한 메모리를 스택에 할당받습니다.

(2) 메서드가 수행을 마치면 사용했던 메모리 공간을 반환합니다.

(3) 호출 스택 맨 위에 있는 메서드가 현재 실행 중인 메서드입니다.

(4) 각 메서드의 아래에 있는 메서드가 위의 메서드를 호출한 메서드입니다.

 

 

 

 

 

3-8. 기본형 매개변수와 참조형 매개변수

- 기본형 매개변수 : 변수의 값을 읽을 수만 있습니다.

- 참조형 매개변수 : 변수의 값을 읽고 수정할 수 있습니다.

 

 

 

 

 

3-9. 재귀 호출(Recursive call)

- 재귀 호출이란, 메서드 내부에서 메서드가 자기 자신을 또 다시 호출하는 행위를 의미합니다.

 

- 재귀 호출은 반복문으로 바꿀 수 있으며 반복문보다 성능이 좋지 않습니다.

 

- 이해하기 쉽고 간결한 코드를 작성할 수 있습니다.

 

- 재귀 호출의 예시 : 팩토리얼, 제곱, 트리 운행,. 폴더 표시 목록 등...

// 팩토리얼 메서드의 재귀 호출
long factorialCal(int n) {
    long result = 0;
    
    if (n == 1) { result = 1; }
    else { result = n * factorialCal(n-1); }
    
    return result;
}

 

 

 

 

 

3-10. 클래스(Static) 메서드와 인스턴스 메서드

(1) 클래스(Static) 메서드

- 객체 생성 없이, "클래스명.메서드명();"으로 호출 가능합니다

 

- 인스턴스 변수나 인스턴스 메서드와는 관련 없는 작업을 수행하는 메서드입니다.

 

- 메서드 내부에서 인스턴스 변수를 사용할 수 없습니다. 

이러한 이유 때문에 인스턴스 변수를 사용하지 않는 메서드에 Static 키워드를 붙입니다.

 

- 메서드 내부에서 인스턴스 변수를 사용하지 않는다면 static을 붙이는 것을 고려합니다.

 

 

 

(2) 인스턴스 메서드

- 객체  생성 후 "참조변수명.메서드명();"으로 호출 가능합니다.

 

- 인스턴스 변수나, 인스턴스 메서드와 관련된 작업을 하는 메서드입니다.

 

- 메서드 내부에서 인스턴스 변수를 사용할 수 있습니다.

class OOP {
    long a, b;

    // 인스턴스 메서드
    long add(long a, long b) {
        return a + b;
    }

    // 클래스 메서드(Static 메서드)
    static long add2(long a, long b) {
        return a + b;
    }

    public static void main(String[] args) {
        // 클래스 메서드 호출
        System.out.println(OOP.add2(200L, 100L));   // 300

        // 클래스의 인스턴스 생성
        OOP mm = new OOP();
        
        // 생성된 객체의 인스턴스 변수에 값 할당
        mm.a = 20L;
        mm.b = 10L;

        // 인스턴스 메서드 호출
        System.out.println(mm.add(mm.a, mm.b));   // 30
    }
}

 

 

 

 

 

3-11. 멤버 간의 참조와 호출 - 메서드의 호출

- 동일한 클래스의 멤버 간에는 객체 생성이나 참조변수 없이 참조가 가능합니다.

 

- 그러나 Static 계열의 멤버들은 인스턴스 멤버들을 참조할 수 없습니다.

(Static 메서드는 인스턴스 변수를 사용할 수 없음)

 

- 인스턴스 메서드 내부에서 인스턴스 변수를 사용하는 경우는 인스턴스 메서드 호출 행위가 객체 생성 시 가능한 경우이므로, 인스턴스 변수도 사용할 수 있습니다.

 

- Static 메서드는 해당 클래스에 대한 객체 생성 없이 호출이 가능하나 인스턴스 변수의 경우 객체 생성이 이루어졌는지 장담할 수 없기에, Static 메서드(클래스 메서드)에선 인스턴스 변수를 사용할 수 없습니다.

class TestClass {
    // 인스턴스 변수
    int instanceVariable;  
    
    // 클래스 변수
    static int classVariable;
    
    // 인스턴스 메서드
    void instanceMethod() {
        System.out.println(instanceVariable);  // 인스턴스 변수 사용 가능
        System.out.println(classVariable);   // 클래스 변수 사용 가능
    }
    
    // 클래스(Static) 메서드
    static void classMethod() {
        // System.out.println(instanceVariable);   인스턴스 변수 사용 불가
        System.out.println(classVariable);   // 클래스 변수 사용 가능
    }
}

 

 

 

 

- Static 메서드는 이러한 이유 때문에 인스턴스 메서드도 호출할 수 없습니다.

class TestClass {
    // 인스턴스 메서드
    void instanceMethod() {}
    
    // Static(클래스) 메서드
    static void classMethod {}
    
    // 인스턴스 메서드
    void instanceMethod2() {
        instanceMethod();    // 다른 인스턴스 메서드를 호출 가능
        classMethod();     // Static(클래스) 메서드를 호출 가능
    {
    
    // Static(클래스) 메서드
    static void classMethod2() {
        // instanceMethod();     인스턴스 메서드 호출 불가
        classMethod();      // Static(클래스) 메서드 호출 가능 
    }
}

 

 

 

 

 

 

 

- 학부에서 수강했던 전공 수업 내용을 정리하는 포스팅입니다.

- 내용 중에서 오타 또는 잘못된 내용이 있을 시 지적해 주시기 바랍니다.

댓글