본문 바로가기
✏️Java 공부/Java의 정석

[Java 공부/Java의 정석] Chapter.06 : 객체지향 프로그래밍 1 - 2 (변수와 메서드)

by 코코의 주인 2022. 7. 1.

변수의 선언 위치에 따른 변수의 종류

변수는 클래스 변수, 인스턴스 변수, 지역 변수 세 종류가 있다. 변수의 종류를 결정짓는 중요한 요소는 '변수가 선언된 위치'이므로 변수의 종류를 파악하기 위해서는 변수가 어느 영역에서 선언되었는지를 확인하는 것이 매우 중요하다.

class Animal {
    String name;    //인스턴스 변수
    static int age; //클래스 변수(static 변수)
    
    void method() {
        int localVariable;  //지역 변수
    } 
}
변수의 종류 선언 위치 생성 시기
인스턴스 변수(instance variable) 클래스 영역 인스턴스가 생성되었을 때
클래스 변수(class variable) 클래스가 메모리에 올라갈 떄
 지역 변수(local variable) 클래스 영역 이외의 영역(메서드, 생성자 등) 변수 선언문이 수행되었을 떄

1. 인스턴스 변수(instance variable)

 클래스 영역에 선언된다. 인스턴스는 독립적인 저장공간을 가지므로 서로 다른 값을 가질 수 있다. 인스턴스마다 고유한 상태를 유지해야 하는 속성의 경우, 인스턴스 변수로 선언한다.

 

2. 클래스 변수(class variable)

 인스턴스 변수 앞에 static을 붙여서 클래스 변수를 선언한다. 인스턴스마다 독립적인 저장 공간을 갖는 인스턴스 변수와는 달리, 클래스 변수는 클래스에서 생성된 모든 인스턴스가 공통된 저장공간(변수)을 공유하게 된다. 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야 하는 속성의 경우, 클래스 변수로 선언한다.

 

3. 지역 변수(local variable)

 메서드 내에 선언되어 메서드 내에서만 사용 가능하며, 메서드가 종료되면 소멸되어 사용할 수 없다. for문 또는 while문의 블럭 내에 선언된 지역변수는 그 변수가 선언된 블록 { } 내에서만 사용 가능하며, 블록 { }을 벗어나면 소멸되어 사용할 수 없게 된다.


클래스 변수와 인스턴스 변수

인스턴스 변수

class Animal {
    String name;	//인스턴스 변수
    int age;		//인스턴스 변수
}
public class VariableAndMethod {

    public static void main(String[] args) {
        Animal cat = new Animal();
        Animal dog = new Animal();

        cat.name = "코코";
        cat.age = 2;
        dog.name = "덕구";
        dog.age = 7;

        System.out.println("고양이의 이름은: " + cat.name);   //"고양이의 이름은: 코코" 출력
        System.out.println("고양이의 나이는: " + cat.age);	//"고양이의 나이는: 2" 출력
        
        System.out.println("개의 이름은: " + dog.name);	//"개의 이름은: 덕구" 출력
        System.out.println("개의 나이는: " +dog.age);	//"개의 나이는: 7" 출력

    }
}

 Animal 클래스 안에 name과 age를 모두 인스턴스 변수로 선언하였다. Animal 클래스로 cat과 dog라는 인스턴스를 각각 생성하였고, 각 인스턴스 별로 이름과 나이를 입력하고 출력하였다. 클래스 안의 변수가 모두 인스턴스 변수이기 때문에 cat과 dog의 이름, 나이가 인스턴스별로 다르게 출력되는 것을 볼 수 있다.


클래스 변수

이번엔 Animal 클래스의 age를 클래스 변수로 선언해보자

class Animal {
    String name;	//인스턴스 변수
    static int age;	//클래스 변수
}
public class VariableAndMethod {

    public static void main(String[] args) {
        Animal cat = new Animal();
        Animal dog = new Animal();

        cat.name = "코코";
        cat.age = 2;
        dog.name = "덕구";
        dog.age = 7;

        System.out.println("고양이의 이름은: " + cat.name);   //"고양이의 이름은: 코코" 출력
        System.out.println("고양이의 나이는: " + cat.age);	//"고양이의 나이는: 7" 출력
        
        System.out.println("개의 이름은: " + dog.name);	//"개의 이름은: 덕구" 출력
        System.out.println("개의 나이는: " +dog.age);	//"개의 나이는: 7" 출력


    }

 분명 cat의  age를 2로 변경했음에도 불구하고 cat의 나이가 dog와 같은 7로 나온다. Animal의 인스턴스인 cat과 dog가 클래스 변수인 age를 공유하기 때문에 일어난 대참사다. 어느 한 쪽의 age를 변경하면 다른 쪽의 age도 같이 변경되는 것이다. 


메서드

메서드(method)는 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것이다. 수학의 함수(function)과 유사하며, C나 C++에서 함수라고 부르던 것과 같은 개념이라고 보면 된다.

 메서드에서 중요한 것은 어떤 값(입력)을 넣으면 반환하는 값(출력)이 있다는 것이다. 이 메서드가 내부적으로 어떤 과정을 거쳐 결과를 만들어내는지는 중요하지 않다. 이러한 특성을 블랙박스(black box)라고 한다.


메서드를 사용하는 이유

1 . 높은 재사용성(reusability)

 한번 만들어 놓은 메서드는 몇 번이고 호출할 수 있으며, 다른 프로그램에서도 사용이 가능하다.

 

2. 중복된 코드의 제거

  프로그램을 작성하면서 같은 내용의 문장들의 반복해서 나타나는 경우가 있다. 이렇게 반복되는 문장들을 묶어서 하나의 메서드로 작성해 놓으면 반복되는 문장들 대신 메서드를 호출하는 한 문장으로 대체할 수 있다. 

 

중복되는 코드

public static void main(String[] args) {

	for(int i = 5; i > 0; i--) {	//5,4,3,2,1 카운트 다운
    	System.out.println(i);
    }
          ... 중간 생략 ...
          
	for(int i = 5; i > 0; i--) {
    	System.out.println(i);
    }
}

 만약 10부터 1까지 카운트다운으로 수정사항이 발생한 경우, 코드가 중복되는 모든 부분을 수정해야 하는 불편함이 발생한다. 하나라도 놓치면 오류가 발생할 수도 있다.

 

메서드를 사용

static void countDown() {
	for(int i = 5; i > 0; i--) {
    	System.out.println(i);
    }
}

public static void main(String[] args) {

	countDown();
    
          ... 중간 생략 ...
          
	countDown();
}

메서드를 사용하게 되면 변경 사항이 발생했을 경우, 메서드에서 한 번만 수정하면 된다. 오류가 발생할 확률도 줄어드는 것이다.

 

3. 프로그램의 구조화

 개발을 하다보면 갈수록 복잡한 프로그램을 작성하게 될 것이다. 이 경우 몇 천줄, 몇 만줄이 넘는 프로그램을 작성하게 될텐데, 이러한 큰 규모의 프로그램에서는 문장들을 작업단위로 나눠서 여러 개의 멘서드에 담아 프로그램의 구조를 단순화 시키는 것이 필수적이다.


메서드의 호출

 메서드의 호출은 다룰 내용이 크게 없어서 하나만 짚고 넘어가겠다.

 같은 클래스 내의 메서드끼리는 참조변수를 사용하지 않고도 서로 호출이 가능하지만, static 메서드는 같은 클래스 내의 인스턴스 메서드를 호출할 수 없다. 이게 무슨 소린가 싶어서 예시를 들겠다.

 

static 메서드에서 인스턴스 메서드를 호출하는 예

public class sample {

    void sayHello() {	//인스턴스 메서드
        System.out.println("hello");
    }

    public static void main (String args[]) {	//static 메서드
        sayHello();	//호출 불가(X)
    }
}

위 코드는 static 메서드(main)에서 인스턴스 메서드(sayHello)를 호출하려는 코드다. 당연히 실행은 되지 않는다.

 

static 메서드에서 static 메서드를 호출하는 예

public class sample {

    static void sayHello() {	//static 메서드
        System.out.println("hello");
    }

    public static void main (String args[]) {	//static 메서드
        sayHello();	//호출 가능(O)
    }
}

 

그렇다면 static 메서드에서 static 메서드의 호출은 가능할까?

가능하다!!

 

인스턴스 메서드에서 인스턴스 메서드를 호출하는 예

public class sample {

    void sayHello() {	//인스턴스 메서드
        System.out.println("hello");
    }

    void introduce() {	//인스턴스 메서드
        sayHello();	//호출 가능(O)
    }
    public static void main (String args[]) {	//static 메서드
        sample s = new sample();	//인스턴스 생성
        s.introduce();	//참조변수를 통한 호출 가능(O)
    }
}

인스턴스 메서드에서 인스턴스 메서드의 호출도 가능하다.

그럼 대체 어떻게 해야 static 메서드에서 인스턴스 메서드의 호출이 가능할까?
위 코드에 답이 나와있다.


총평

뒤에 메서드 선언, 호출, return문 등과 같은 내용이 추가로 있지만 굳이 적어야 하나 싶어서 내용에 담지 않았다.

글을 작성하면서 변수의 종류와 특징에 대해 확실하게 이해할 수 있었다.

댓글