<Java> 객체지향프로그래밍 1

  • 지금까지 자바의 기초적인 문법 요소들에 대해 배워 봤습니다. 이제 자바의 꽃이라 볼 수 있는 OOP(Object Oriented Programming)에 대해 알아보겠습니다.
  • 본격적인 문법 얘기를 시작하기 전에 객체 지향이론의 기본 개념에 대해 알아봅시다.
  • 객체지향은 “실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물간의 상호작용이다”라는 것입니다.처음 위와 같은 정의를 들으면 쉽게 이해가 가지 않습니다.그래서 정의보다는 객체지향의 배경을 이해하면 정의를 좀 더 이해 할 수 있습니다.
  • 객체지향언어가 생기기전에는 절차지향언어로 모든 프로그램이 작성되었습니다.쉽게 말해 규모가 큰 프로그램에서 코드를 재사용하지 않고 유지보수에 어려움이 큰 구조로 코딩을 하고 있었다고 생각하시면 됩니다. 이러한 상황에서 점점 더 큰 스케일의 프로그램이 요구되었고 이에 대한 요구로 객체지향언어가 떠오르기 시작했습니다.
  • 위에 살짝 언급된 것처럼 객체지향의 특징이 몇가지가 있습니다.코드를 재사용하며 관리에 용이한 구조인 동시에 유지 보수에 유리하다는 특징이 있습니다.
  • 사실 이러한 개념에 얽매이기보다는 앞서 배운 문법에 기초하여 직접 코드를 쳐보면서 기능 단위로 프로그램을 완성시키면서 객체지향에 대한 생각을 하는 것이 바람직 할 것 같습니다.

클래스와 객체

클래스와 객체의 정의와 용도

  • 클래스란 ‘객체를 정의해 놓은 것’, 또는 클래스는 ‘객체의 설계도 또는 틀’이라고 정의 할 수 있습니다.
  • 객체는 사전적인 정의로는 ‘실존하는 것’입니다.우리가 실제로 보는 맥북,책상,의자 등등 사물들이 곧 객체라고 볼 수 있습니다.우리가 배우는 객체지향이론에서는 사전적의미인 사물뿐만 아니라 개념이나 논리와 같은 무형적인것들도 객체로 간주합니다.
  • 위의 개념을 실생활 예제로 빗대어 보겠습니다. 갤럭시라는 휴대폰은 해당 기기에 알맞은 각각의 설계도들이 존재할 것입니다.이러한 설계도가 클래스이며, 설계도를 기반으로 만들어진 갤럭시 스마트폰이 실제 객체라고 이해하면 됩니다.
  • 우리가 갤럭시를 쓰기위해서는 갤럭시폰이 필요하지 이의 설계도가 필요하지는 않습니다.즉, 객체가 필요하지 클래스가 필요하지는 않습니다.
  • 그리고 갤럭시 설계도를 통해 갤럭시 스마트폰이 만들어진 후에야 갤럭시를 사용할 수 있습니다.즉, 프로그래밍에서 먼저 클래스를 작성한 다음, 해당 클래스로부터 객체를 생성하여 사용합니다.

객체와 인스턴스

  • 위의 두 개념을 비교하는 것은 문법적인 내용이라기 보다는 컴퓨터 세계에서 상식에 가까운 지식들이니 알아두면 좋습니다.
  • 클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화라고 하며, 어떤 클래스로부터 만들어진 객체를 그 클래스의 인스턴스라고 합니다.
  • 예를 들어, Order라는 Class로부터 생성된 객체를 Order 클래스의 인스턴스라 합니다.결국 객체와 인스턴스는 동일한 의미를 가지지만 객체가 인스턴스를 포함하기 때문에 좀 더 포괄적인 상위 개념이라 보시면 될 것 같습니다.인스턴스의 경우 어떤 클래스로부터 만들어졌는지에 초점을 둔 개념이라 생각하면 좋을 것 같습니다.
  • 예를 들어,쇼핑몰에서 주문을 생성하는 경우가 있다고 가정합시다.단순히 주문이라는 용어 자체에 초점을 두면 객체라는 표현을 사용하는 것이 더 좋습니다.하지만, Order클래스로부터 생성된 주문에 초점을 두게 될 경우, Order클래스로부터 생성된 인스턴스라는 표현이 더 적절할 것 입니다.

객체의 구성요소 - 속성과 기능

  • 객체는 속성과 기능, 두 종류의 구성요소로 이루어져 있으며 일반적으로 객체는 다수의 속성과 다수의 기능을 가집니다.즉, 객체는 속성과 기능의 집합이라고 볼 수 있습니다.그리고 이렇난 속성과 기능은 객체의 멤버(member)라는 표현을 사용합니다.
  • 클래스는 객체의 설계도, 즉 객체의 정의이므로 클래스에는 객체의 모든 속성과 기능들이 정의되어 있습니다.클래스로부터 객체를 생성하면 클래스에 정의된 속성과 기능을 가진 객체가 만들어 지는 것입니다.
  • 언급된 속성과 기능은 아래와 같이 여러가지 용어가 있습니다.bold처리된 두가지 용어가 주로 사용됩니다.
  • 속성 : member variable(변수),attribute,field, state
  • 기능 : method(메서드), function,behavior
  • 이제 예제를 통해 실제 클래스를 정의하고 객체를 만들어 봅시다.
public class TvTest {
    public static void main(String[] args) {
        TV t;
        t = new TV();
        t.channel = 12;
        t.setChannelDown();
        System.out.println("t.channel = " + t.channel);
    }
}

class TV {
    String color;
    boolean power;
    int channel;

    void setPower() {
        power = !power;
    }

    void setChannelUp() {
        ++channel;
    }

    void setChannelDown() {
        --channel;
    }
}
  • 쉬운 코드이지만 상세하게 설명하겠습니다.Tv t를 통해서 t라는 Tv 타입의 참조변수를 생성합니다.이후 new TV()를 통해 새로운 TV 타입의 객체를 생성합니다.그리고 나서 생성된 객체의 주소를 대입 연산자를 통해 t라는 참조변수에 넣어줍니다.그러면 우리가 앞서 배운 Reference Type의 변수가 생성되고 초기화 되는 것입니다.이후 참조변수 t를 통해 TV 인스턴스에 접근 가능하며 내부의 변수와 메서드 또한 사용할 수 있습니다.
  • 조금 더 심화된 내용을 봅시다.위의 main 메서드 내에 아래와 같은 코드가 있다고 가정합시다.
		TV t1 = new TV();
		TV t2 = new TV();
		t2 = t1;
		t1.channel = 7;
        System.out.println("t.channel = " + t.channel);
        System.out.println("t.channel = " + t.channel);
  • 우선 인스턴스에 접근 가능한 참조변수가 두개 있습니다.그리고 t2라는 참조변수에 t1의 참조값을 대입연산자를 통해 넣어줍니다.즉, t2가 가지고 있던 인스턴스의 주솟값이 t1이 가지고 있는 주솟값으로 바뀐것입니다.그러면 당연히 t1,t2 모두 하나의 인스턴스를 참조하고 있기에 동일한 메서드와 변수에 접근합니다.
  • 출력문을 확인해보면 둘다 7을 출력하는 것을 확인할 수 있습니다.
  • 그러면, 더 이상 참조를 받지 않는 기존의 t2가 참조하던 인스턴스는 어떻게 될까요? 한번 언급한적 있는 Garbage Collector(GC)에 의해 자동적으로 메모리에서 제거됩니다.
  • 다시 한번 정리하면 자신을 참조하고 있는 참조변수가 하나도 없는 인스턴스는 더 이상 사용되어질 수 없으므로 GC에 의해 메모리 공간이 수거됩니다.

클래스의 또 다른 정의

  • 지금껏 우리는 클래스는 객체를 생성하기 위한 설계도 또는 틀이며 속성과 기능으로 구성된다고 배웠습니다.이러한 정의는 객체지향 관점에서 내린 정의이며 프로그래밍 관점에서의 클래스의 정의를 한번 알아봅시다.
  1. 클래스 => 데이터와 함수의 결합체
  • 프로그래밍에서 데이터 처리를 위한 자료구조의 발전 형태는 아래와 같습니다.
  • 하나의 데이터를 저장하기 위해 변수, 여러개의 변수를 저장하려고 배열 그리고 다양한 타입의 종류에 상관없이 저장하려고 구조체 그리고 최종적으로 함수까지 포함하는 클래스가 등장합니다.
  • 단적인 예로 C언어에서 문자열을 다룰때는 문자의 배열(char타입의 배열)로 다루지만 자바에서는 String을 통해서 다룹니다.이러한 형태를 취하는 이유는 문자열과 해당 문자열을 다루는데 필요한 각종 기능(메서드)을 편하게 사용할 수 있기 때문입니다.
  1. 클래스 => 사용자 정의 타입(user-defined type)
  • 각각의 프로그래밍 언어에서 제공하는 자료형(Primitive Type,일부 Reference Type)외에 프로그래머가 본인이 직접 사용하기 위해 만들어낸 타입의 변수를 user-defined type 변수라고 합니다.다른 언어에서도 마찬가지로 만들어 낼 수 있으며 자바와 같은 객체 지향언어에서는 클래스가 곧 사용자 정의 타입입니다.

변수와 메서드

변수의 종류

  • 지금껏 우리는 수많은 변수를 선언하고 초기화하며 사용했습니다.이제는 이러한 변수가 선언되는 위치에 따른 종류를 알아보겠습니다.변수는 클래스변수,인스턴스변수,지역변수 3가지 종류가 있습니다.앞서 언급한 클래스 내의 변수인 멤버변수를 제외한 나머지 변수들은 모두 지역변수이며, 멤버 변수 중 static 키워드가 붙으면 클래스 변수, 그렇지 않으면 인스턴스 변수입니다.
  • 아래의 코드를 통해 알아봅시다.
class Variables
{
		int iv; //instanceValue
		static int cv; //classValue

		void method(){
			int lv = 4; // localValue
		}

}
  • 먼저 살펴볼 변수는 인스턴스 변수입니다. 이는 이름에서도 알 수 있듯이 클래스의 인스턴스를 생성할 때 만들어 집니다.그렇기 때문에 인스턴스 변수 값을 읽어 오거나 저장하기 위해서는 먼저 인스턴스를 생성해야합니다.또한 인스턴스의 경우 메모리 공간상에 독립적인 저장공간을 가집니다.그래서 인스턴스 변수의 경우 인스턴스마다 서로 다른 값을 가질 수 있습니다.즉,인스턴스마다 고유한 상태를 유지해야하는 경우, 인스턴스 변수로 선언해야합니다.
  • 다음은 cv,클래스 변수입니다.이는 인스턴스 변수 앞에 static을 붙여주기만 하면 됩니다.독립적인 공간을 가져 값을 다르게 가질 수 있는 인스턴스 변수와 달리 이는 모든 인스턴스가 공통된 저장공간을 공유합니다.즉, 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야하는 경우 사용합니다.
  • static 키워드에 대한 좀 더 설명해보면, 정적인이라는 뜻을 가졌기에 변하지 않는 속성이라고 생각하시면 좋습니다.이 키워드가 붙으면 클래스가 메모리에 로딩될 때 생성되어 프로그램이 종료 될때까지 유지됩니다.즉, 생명주기가 프로그램과 동일하다고 볼 수 있습니다.

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

  • 문법적으로 위의 두가지 변수가 어떤식으로 다른지는 알아보았습니다.이제 예제를 통해 실제 코드를 보겠습니다.
  • 예제의 경우 카드 클래스로부터 생성된 인스턴스를 통해 변수를 다뤄봅니다.카드 클래스는 무늬,숫자,폭,높이를 변수로 가집니다.
public class CardTest {
    public static void main(String[] args) {
        System.out.println("Card.height = " + Card.height);
        System.out.println("Card.width = " + Card.width);
        /*
        * Set Instance Variable
        * */
        Card c1 = new Card();
        c1.kind = "Heart";
        c1.number = 7;

        Card c2 = new Card();
        c2.kind = "Spade";
        c2.number = 4;
        /*
        * Set Class Variable
        * */
        c1.width = 50;
        c1.height = 150;

        System.out.println("c1.kind = " + c1.kind);
        System.out.println("c1.number = " + c1.number);
        System.out.println("c1.width = " + c1.width);
        System.out.println("c1.height = " + c1.height);
        
        System.out.println("c2.kind = " + c2.kind);
        System.out.println("c2.number = " + c2.number);
        System.out.println("c2.width = " + c2.width);
        System.out.println("c2.height = " + c2.height);
        
    }
}

public class Card {
    String kind;
    int number;
    static int width = 100;
    static int height = 250;
}
  • 코드에서 알 수 있듯이, 폭과 높이는 클래스 변수로 선언했습니다.이는 곧 모든 인스턴스가 공유하는 변수이기에 하나의 카드 인스턴스에서 값을 변경해도 모든 인스턴스에서 해당 값이 변경된다는 뜻입니다.즉, c1 인스턴스의 클래스 변수의 값을 변경하면 c2 인스턴스의 값도 자동적으로 변경됩니다.
  • 이와 반대로 인스턴스 변수의 경우 c1과 c2 각기 다른 값을 유지하고 있습니다.

메서드의 선언과 구현

  • 메서드는 앞서 언급한 것처럼 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것입니다.만약 이해가 어렵다면 수학에서의 함수 y = f(x)를 생각하셔도 됩니다.변수 x를 넣으면 결과값으로 y가 반홥됩니다.메서드도 이처럼 어떠한 값을 넣을 경우, 그에 대한 반환값을 반환해주는 구조입니다.예를 들어 Math.sqrt()라는 메서드를 확인해봅시다.이는 16이라는 정수를 입력하면 4라는 값을 반환해줍니다.즉, 루트 연산을 수행해주는 메서드임을 유추 할 수 있습니다.추가적으로 모든 메서드가 입력값과 반환값을 반드시 가지지는 않습니다.이는 아래에 나오는 실제 메서드 구조를 보며 좀 더 설명하겠습니다.
  • 메서드는 크게 선언부구현부로 나누어져 있습니다.메서드를 정의한다라는 문장의 의미는 선언부와 구현부를 작성하는 것을 뜻하며 아래와 같은 형식으로 정의됩니다.
  • 메서드 선언부는 ‘메서드의 이름’과 ‘매개변수 선언’,그리고 ‘반환타입’으로 구성되어 있으며, 메서드가 작업을 수행하기 위해 어떤 값들을 필요로 하고 작업의 결과로 어떤 타입의 값을 반환하는지에 대한 정보를 제공합니다.
  • 예를 들어 아래에 정의된 메서드의 경우 두개의 정수를 입력받은 뒤, 두 값을 더한 int타입의 값을 반환해줍니다.
int add(int x, int y){
		int res = x + y;
		return res;
}
  • 매개변수란 메서드가 작업을 수행하는데 필요한 값들이며 선언을 통해 입력받습니다.필요한 값의 개수만큼 변수를 선언하며 각 변수 간의 구분은 쉼표를 이용합니다.위의 코드에서는 (int x,int y)부분이 매개변수 선언 부분입니다.만약 값을 입력받을 필요가 없는 메서드의 경우 괄호 안을 비워두면 됩니다.참고로 매개변수도 메서드내에 선언된 것으로 간주되므로 지역변수입니다.
  • 위의 예제에서 메서드의 이름은 add이며 앞서 배운 변수의 명명규칙과 동일한 컨벤션을 적용하여 명명하면 됩니다.
  • 마지막으로 반환타입을 살펴봅니다.위의 예제에는 메서드의 이름 앞에 명시된 데이터 타입인 int입니다.메서드 내부에 return 문 뒤에 나오는 변수를 살펴보면 int타입의 변수를 반환하고 있습니다.즉, return 문 다음에 나오는 변수의 자료형은 메서드의 반환타입과 동일해야 합니다.만약 반환타입이 필요없는 메서드의 경우 void라는 키워드를 사용해서 반환타입을 명시해줍니다.아래의 예제를 보면 됩니다.
void printMultiply(){
	for(int i = 1; i <= 9; i++){
		for(int j = 2;j<= 9; j++){
			System.out.print(j*i);
		}
		System.out.println();
	}
}
  • 구구단을 출력해주는 예제입니다.이는 반환타입은 물론 매개변수도 필요하지 않은 메서드입니다.

인자(argument)와 매개변수(parameter)

  • 우선 위의 두가지 개념을 구분하기 위해서 함수의 호출을 알아야합니다.이미 너무나도 당연하게 함수를 호출하여 사용한적이 많습니다.코드를 통해 살펴보면 다음과 같습니다.앞서 진행한 두 예제를 활용해보겠습니다.
printMultiply();
int result = add(3,10);
  • 위와 같은 방식으로 함수를 호출하여 사용하면 됩니다.
  • 여기서 add 함수를 호출할때 입력된 3과 10이라는 int타입의 변수는 argument라고 구분합니다.반면에 add 메서드의 선언부에서 생성된 x,y라는 int타입의 변수들은 parameter라고 합니다.이 두가지 개념의 차이는 프로그래밍 문법적으로 중요하다라기보다는 상식적인 개념에 가까워 알아두면 좋습니다.

return문

  • return문은 현재 실행중인 메서드를 종료하고 종료된 메서드를 호출한 메서드로 돌아갑니다.원칙대로라면 모든 메서드는 적어도 하나의 return문을 가져합니다.그러면 void 타입인 경우 return문이 존재하지 않았는데 어떤식으로 처리를 했을까요? 컴파일러가 메서드의 마지막에 return;을 자동으로 추가하는 방식으로 처리합니다.
  • 그러나 반환타입이 void가 아닌 경우에는 반드시 return문이 존재해야합니다.없을 경우 흔히 말하는 컴파일 에러(compile error)가 발생합니다.사용하는 IDE에서 빨간줄이 뜹니다.

JVM의 메모리 구조

  • 앞선 내용에서 변수,클래스 등등 다양한 요소들이 메모리에 할당된다는 것은 배웠을 것입니다.그러면 이제 JVM이 어떻게 이러한 요소들을 메모리에 할당시키는지 알아보겠습니다.Computer Science와도 관련이 깊으니 알아두면 좋습니다.
  • 응용 프로그램이 실행되면, JVM은 OS로부터 해당 프로그램을 수행하는데 필요한 메모리 공간을 할당받고 이 공간을 용도에 따라 여러 영역으로 나눠 관리합니다.
  • 우선 도식화시킨 그림은 아래와 같습니다. 각각의 영역에 대해 알아봅시다.
  1. Method Area(메서드 영역) : 프로그램 실행 중 어떤 클래스가 사용되면,JVM은 해당 클래스의 클래스파일을 읽고 해당 클래스의 정보를 메서드영역에 저장합니다.이 때, 그 클래스의 클래스 변수도 함께 생성됩니다.
  2. Heap(힙 영역) : 인스턴스가 생성되는 공간, 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 생성됩니다.즉, 인스턴스 변수들이 생성되는 공간입니다.
  3. Call Stack : 이 영역은 메서드의 작업에 필요한 메모리 공간을 제공합니다.메서드가 호출되면 Call Stack에 호출된 메서드를 위한 메모리가 할당되며, 이 메모리는 메서드가 작업을 수행하는 동안 지역변수들과 연산의 중간결과 등을 저장하는데 사용됩니다. 그리고 메서드가 종료 될 때 할당되었던 메모리공간은 반환됩니다.
  • 이렇게 3가지 영역에 대해 알아보았습니다. 사실 Stack 자료구조에 대한 이해가 없으면 Call Stack을 이해하기는 어려울 것입니다.해당 내용에 대해 조금 더 설명드리겠습니다.
  • 각각의 개별적인 메서드를 위한 메모리상의 작업공간은 서로 구별되며, 첫 번째로 호출된 메서드(주로 main 메서드)를 위한 공간이 메모리 공간 가장 밑에 존재하고 첫번째 메서드가 호출한 두번째 메서드를 위한 메모리 공간은 첫번째 메서드의 공간 바로위에 할당됩니다.이런식으로 마치 쌓아지는 것처럼 메모리가 할당된다고 해서 Stack이라는 자료구조라 명명했습니다.
  • 결론적으로 Call Stack의 제일 상위에 위치하는 메서드가 현재 실행중인 메서드라는 점을 이해하면 됩니다.
  • 예제를 통해 알아봅시다.
public class CallStackTest {
    public static void main(String[] args) {
        System.out.println("CallStackTest.main-Start");
        firstMethod();
        System.out.println("CallStackTest.main-End");
    }
    static void firstMethod() {
        System.out.println("CallStackTest.firstMethod-Start");
        secondMethod();
        System.out.println("CallStackTest.firstMethod-End");
    }
    static void secondMethod() {
        System.out.println("CallStackTest.secondMethod-Start");
        System.out.println("CallStackTest.secondMethod-End");
    }
}
  • 예제의 결과를 위의 설명과 함께 이해하신다면 스택에 대한 개념이 생긴 것입니다.

Primitive Type Parameter and Reference Type Parameter

  • 위의 두가지 타입의 변수를 메서드의 Parameter로 넘겼을 경우 각각의 차이점에 대해 알아봅시다.
  • 자바에서는 메서드를 호출 할 때 매개변수로 지정한 값을 메서드의 매개변수에 복사해서 넘겨줍니다.매개변수의 타입이 Primitive Type인 경우 그 변수의 값이 복사되지만, Reference Type인 경우에는 인스턴스의 주소가 복사됩니다.
  • 즉, 기본형을 넘겨줄 경우는 단순히 저장된 값만을 주기 때문에 넘어간 인자를 변경하지 못하지만 참조형의 경우 변경이 가능해집니다.
  • 아래 두개의 예제를 통해 이해해봅시다.
class Data{
    int x;
}

public class PrimitiveParamEx {
    public static void main(String[] args) {
        Data d = new Data();
        d.x = 100;
        System.out.println("d.x = " + d.x);
        change(d.x);
        System.out.println("After calling change method");
        System.out.println("d.x = " + d.x);
    }

    static void change(int x) {
        x = 1000;
        System.out.print("PrimitiveParamEx.change() ");
        System.out.println("x = " + x);
    }
}
public class ReferenceParamEx {
    public static void main(String[] args) {
        Data d = new Data();
        d.x = 100;
        System.out.println("d.x = " + d.x);
        change(d);
        System.out.println("After calling change method");
        System.out.println("d.x = " + d.x);
    }

    static void change(Data data) {
        data.x = 1000;
        System.out.print("ReferenceParamEx.change ");
        System.out.println("data.x = " + data.x);
    }
}
  • 두번째 예제에서 change라는 메서드는 Parameter로 Data라는 참조형 변수를 받습니다. 즉, 주솟값을 받는다는 것입니다.그러면 해당 주솟값을 통해 주소내에 존재하는 인스턴스의 field값을 자유롭게 변경할 수 있게 됩니다.
  • 반대로 첫번째 예제의 경우에는 change메서드의 parameter x는 그저 d.x의 값을 복사만 해왔기에 d.x에 대한 변경이 불가능한 것입니다.
  • 결론적으로 Parameter Type이 Reference Type, 즉, 참조하는 주솟값으로 들어올 경우, 해당 메서드에서도 주소에 접근이 가능해지기에 주소내에 있는 값들을 읽고 쓸 수 있습니다.

참조형 반환타입

  • 앞서 배운 매개변수뿐만 아니라 반환타입의 경우에도 참조형(주솟값)이 될 수 있습니다.예제를 통해 바로 알아봅시다.
class ThisData{
    int x;
}

public class ReferenceReturnEx {
    public static void main(String[] args) {
        ThisData thisData = new ThisData();
        thisData.x = 10;

        ThisData thisData1 = copy(thisData);
        System.out.println("thisData.x = " + thisData.x);
        System.out.println("thisData1.x = " + thisData1.x);
    }

    static ThisData copy(ThisData data) {
        ThisData tmp = new ThisData();
        tmp.x = data.x;
        return tmp;
    }
}
  • 설명을 하자면, copy라는 메서드 내에서 생성된 인스턴스의 주소는 tmp입니다.이러한 tmp가 가지는 주솟값이 thisData1이라는 또 다른 참조변수에 대입연산 되어집니다.즉, 두가지 참조변수가 가르키는 인스턴스가 동일하다는 의미이죠.하지만 copy 메서드가 종료됨에따라 tmp 변수는 사라지게 되고 결국 thisData1 참조변수가 해당 주소에 존재하는 인스턴스를 참조하고 있습니다.즉, 복사가 잘 이루어졌다라고 보면 됩니다.

클래스 메서드(static 메서드)와 인스턴스 메서드

  • 저희가 클래스 변수에서 배웠듯이, 인스턴스를 생성하지 않고도 사용가능한 변수가 클래스 변수였습니다.반면에 인스턴스, 즉 객체를 생성해야만 사용 가능한 메서드는 인스턴스 메서드입니다.
  • 사실 처음 배울때는 위와 같은 개념이 조금 헷갈릴 수도 있는데 다음과 같이 정리해보겠습니다.
  1. 클래스 영역에 선언된 변수 멤버변수입니다. 멤버변수 중에서 static키워드가 붙은 것은 클래스변수, static이 붙지 않으면 인스턴스 변수입니다.
  2. 클래스를 설계할때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙여 클래스변수로 취급해야합니다.
  3. 클래스 변수는 인스턴스를 생성하지 않아도 사용가능합니다.
  4. 클래스 메서드는 이와 마찬가지 일뿐더러, 인스턴스 변수를 사용할 수 없습니다.
  5. 메서드 내에서 인스턴스 변수를 사용하지 않으면, static을 붙여 클래스 메서드로 취급해야 합니다.
  • 위의 내용을 천천히 읽어보시면서 용어에 대한 이해만 하시면 클래스 설계 시 쉽게 적용 시킬수 있을 것입니다.

Ref: 자바의 정석 - 남궁성