Java 08. 객체지향 프로그래밍 Ⅰ 객체 - swkim0128/PARA GitHub Wiki


type: Java archive: false

클래스와 객체

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


클래스의 정의 - 클래스란 객체를 정의해 놓은 것이다.
클래스의 용도 - 클래스는 객체를 생성하는 데 사용된다.

객체지향이론에서는 사물과 같은 유형적인 것뿐만 아니라, 개념이나 논리와 같은 무형적인 것들도 객체로 간주한다.

객체의 정의 - 실제로 존재하는 것, 사물 또는 개념
객체의 용도 - 객체가 가지고 있는 기능과 속성에 따라 다름

유형의 객체 - 책상, 의자, 자동차, TV와 같은 사물
무형의 객체 - 수학공식, 프로그램 에러와 같은 논리나 개념

객체와 인스턴스


클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화(instantiate)라고 하며, 어떤 클래스로부터 만들어진 객체를 그 클래스의 인스턴스(instance)라고 한다.

클래스 → 인스턴스(객체)

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


속성(property) - 멤버변수(member variable), 특성(attribute), 필드(field), 상태(state)
기능(function) - 메서드(method), 행위(begavior), 함수(function)

인스턴스의 생성과 사용


클래스명 변수명; // 클래스의 객체를 참조하기 위한 참조변수를 선언한다.
변수명 = new 클래스명(); // 클래스의 객체를 생성 후, 객체의 주소를 참조변수에 저장한다.

클래스의 또 다른 정의


클래스는 '객체를 생성하기 위한 틀'이며 '클래스는 속성과 기능으로 정의되어있다.' - 객체지향이론의 관점.

프로그래밍적인 관점

  1. 클래스 - 데이터와 함수의 결합

    프로그래밍언어에서 데이터 처리를 위한 데이터 저장형태의 발전과정

    변수 - 하나의 데이터를 저장할 수 있는 공간
    배열 - 같은 종류의 여러 데이터를 하나의 집합으로 저장할 수 있는 공간
    구조체 - 서로 관련된 여러 데이터를 종류에 관계없이 하나의 집합으로 저장할 수 있는 공간
    클래스 - 데이터와 함수의 결합(구조체 + 함수)

  2. 클래스 - 사용자정의 타입(user-defined type)

    프로그래밍언어에서 제공하는 자료형(primitive type)외에 프로그래머가 서로 관련된 변수들을 묶어서 하나의 타입으로 새로 추가하는 것을 사용자정의 타입(user-defined type)

변수와 메서드

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


변수는 클래스변수, 인스턴스변수, 지역변수 모두 세 종류가 있다. 변수의 종류를 결정짓는 중요한 요소는 '변수의 선언된 위치'. 멤버벼누를 제외한 나머지 변수들은 모두 지역변수, 멤버변수 중 static이 붙은 것은 클래스변수, 붙지 않은 것은 인스턴스변수이다.

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

    클래스 영역에 선언되며, 클래스의 인스턴스를 생성할 때 만들어진다. 그렇기 때문에 인스턴스 변수의 값을 읽어 오거나 저장하기 위해서는 먼저 인스턴스를 생성해야한다.

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

  2. 클래스변수(class variable)

    클래스 변수를 선언하는 방법은 인스턴스변수 앞에 static을 붙이기만 하면 된다. 클래스변수는 모든 인스턴스가 공통된 저장공간(변수)을 공유하게 된다. 그래서 클래스변수를 공유 변수(shared variable)

    클래스 변수는 인스턴스를 생성하지 않고도 언제라도 바로 사용할 수 있다는 특징이 있으며, '클래스이름.클래스변수'와 같은 형식으로 사용한다.

  3. 지역변수(local variable)

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

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


class Card {
String kind; // 카드의 무늬 - 인스턴스변수
int number; // 카드의 숫자 - 인스턴스변수
static int width = 100; // 카드의 폭 - 클래스변수
static int height = 250; // 카드의 높이 - 클래스변수
}

메서드


메서드는 어떤 작업을 수행하기 위한 명령문의 집합이다. 주로 어떤 값을 입력받아서 처리하고 그 결과를 되돌려 준다.

  • 하나의 메서드는 한 가지 기능만 수행하도록 작성하는 것이 좋다.
  • 반복적으로 수행되어야 하는 여러 문장을 하나의 메서드로 정의해 놓으면 좋다.
  • 관련된 여러 문장을 하나의 메서드로 만들어 놓는 것이 좋다.

return 문


메서드가 정상적으로 종료되는 경우는 다음과 같이 두 가지가 있다.

  • 메서드의 블럭{}내의 마지막 문장까지 수행했을 때
  • 메서드 블럭{}내에 있는 문장을 수행 중 return문을 만났을 때

return 문은 현재 실행 중인 메서드를 종료하고 호출한 메서드로 되돌아가게 한다.

  1. 반환값이 없는 경우 - return문만 써주면 된다.
    return;
  2. 반환값이 있는 경우 - return문 뒤에 반환값을 지정해 주어야 한다.
    return 반환값;
  • 다음 예제는 리턴값이 있는 메서들르 리턴값이 없는 메서드로 바꾸는 방법을 보여준다.
    앞서 배운 참조형 매개변수를 활용하면 리턴값이 없어도 메서드의 실행결과를 얻어 올 수 있다.
int add(int a, int b) {
	return a + b;
}
void add(int a, int b, int[] result) {
	result[0] = a + b;
}

메서드는 단 하나의 값만을 리턴할 수 있지만 이것을 응용하면 여러 개의 값을 리턴받는 것과 같은 효과를 얻을 수 있다.

메서드의 호출


참조변수.메서드이름();
참조변수.메서드이름(값1, 값2, ...);

JVM의 메모리구조


응용프로그램이 실행되면, JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고 JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다. 그 중 3가지 주요영역(method area, 호출스택, heap)

  1. 메서드영역(method area)

    • 프로그램 실행 중 어떤 클래스가 사용되면, JVM은 해당 클래스의 클래스파일(*.class)을 읽어서 분석하여 클래스에 대한 정보(클래스 데이터)를 이곳에 저장한다. 이 때, 그 클래스의 클래스변수(class variable)도 이 영역에 함께 생성된다.
  2. 힙(heap)

    • 인스턴스가 생성되는 공간, 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 생성된다. 즉, 인스턴스변수(intstance variable)들이 생성되는 공간이다.
  3. 호출 스택(call stack 또는 execution stack)

    • 호출스택은 메서드의 작업에 필요한 메모리 공간을 제공한다. 메서드가 호출되면, 호출스택에 호출된 메서드를 위한 메모리가 할당되며, 이 메모리는 메서드가 작업을 수행하는 동안 지역변수(매개변수 포함)들과 연산의 중간결과 등을 저장하는데 사용된다. 그리고 메서드가 작업을 마치면 할당되었던 메모리공간은 반환되어 비워진다.

    호출스택의 특징

    • 메서드가 호출되면 수행에 필요한 만큼의 메모리르 스택에 할당받는다.
    • 메서드가 수행을 마치고나면 사용했던 메모리를 반환한고 스택에서 제거된다.
    • 호출스택의 제일 위에 있는 메서드가 현재 실행 중인 메서드이다.
    • 아래에 있는 메서드가 바로 위의 메서드를 호출한 메서드이다.

기본형 매개변수와 참조형 매개변수


자바에서는 메서드를 호출할 때 매개변수로 지정한 값을 메서드의 매개변수에 복사해서 넘겨준다. 매개변수의 타입이 기본형일 때는 기본형 값이 복사되겠지만, 참조형이면 인스턴스의 주소가 복사된다.

기본형 매개변수 - 변수의 값을 읽기만 할 수 있다. (read only)
참조형 매개변수 - 변수의 값을 읽고 변경할 수 있다. (read & write)

재귀호출(recursive call)


메서드의 내부에서 메서드 자기 자신을 다시 호출하는 것을 재귀호출(recursive call)이라 한다. 반복적인 작업을 해야 하는 메서드에 반복문 대신 재귀호출을 이용하면, 메서드를 훨씬 간단하게 할 수 있는 경우가 있다.

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


변수에서 그랬던 것과 같이, 메서드 앞에 static이 붙어 있으면 클래스메서드이고 붙어 있지 않으면 인스턴스메서드이다.

클래스메서드도 클래스변수처럼, 객체를 생성하지 않고도 '클래스이름.클래스메서드이름(매개변수)'와 같은 식으로 호출이 가능하다.

인스턴스메서드는 인스턴스변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스변수를 필요로 하는 메서드이다.

반면에 메서드 중에서 인스턴스와 관계없는(인스턴스변수나 인스턴스메서드를 사용하지 않는) 메서드를 클래스메서드(static메서드)로 정의한다.

다만 인스턴스변수를 사용하지 않는다고 해서 반드시 클래스메서드로 정의해야하는 것은 아니지만 특별한 이유가 없는 한 그렇게 하는 것이 일반적이다.

  1. 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통적으로 사용해야하는 것에 static을 붙인다.

    • 생성된 각 인스턴스는 서로 독립적이기 떄문에 각 인스턴스의 변수는 서로 다른 값을 유지한다. 그러나 모든 인스턴스에서 같은 값이 유지되어야 하는 변수는 static을 붙여서 클래스변수로 정의해야 한다.
  2. 클래스변수(static 변수)는 인스턴스를 생성하지 않아도 사용할 수 있다.

    • static이 붙은 변수(클래스변수)는 클래스가 메모리에 올라갈 때 이미 자동적으로 생성되기 때문.
  3. 클래스메서드(static메서드)는 인스턴스변수를 사용할 수 없다.

    • 인스턴스변수는 인스턴스가 반드시 존재해야만 사용할 수 있는데, 클래스메서드(static이 븥은 메서드)는 인스턴스 생성 없이 호출가능하므로 클래스 메서드가 호출되었을 때 인스턴스가 존재할 수도 있고 존재하지 않을 수도 있따. 그래서 클래스메서드에서 인스턴스변수의 사용을 금지한다.
      그러나 인스턴스변수나 인스턴스메서드에서는 static이 붙은 멤버들을 사용하는 것이 언제나 가능하다. 인스턴스변수가 존재한다는 것은 static이 붙은 변수가 이미 메모리에 존재한다는 것을 의미하기 때문이다.
  4. 메서드 내에서 인스턴스변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.

    • 메서드의 작업내용 중에서 인스턴스변수를 필요로 한다면, static을 붙일 수 없다. 반대로 인스턴스변수를 필요로 하지 않는다면 static을 붙이자. 메서드 호출시간이 짧아지기 때문에 효율이 높아진다.
      static을 안 붙인 메서드(인스턴스메서드)는 실행 시 호출되어야할 메서드를 찾는 과정이 추가적으로 필요하기 때무에 시간이 더 걸린다.
  • 클래스의 멤버변수 중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있는지 살펴보고 있으면, static을 붙여준다.
  • 작성한 메서드 중에서 인스턴스 변수나 인스턴스 메서드를 사요하지 않는 메서드에 대해서 static을 붙일 것을 고려한다.

클래스멤버와 인스턴스 멤버간의 참조와 호출


같은 클래스에 속한 멤버들 간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출이 가능하다. 단 클래스멤버가 인스턴스멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다.

그 이유는 인스턴스멤버가 존재하는 시점에 클래스멤버는 항상 존재하지만, 클래스멤버가 존재하는 시점에 인스턴스멤버가 존재할 수도 있고 존재하지 않을 수도 있기 때문

인스턴스멤버간의 호출에는 아무런 문제가 없다. 하나의 이스턴스멤버가 존재한다는 것은 인스턴스가 이미 생성되어있다는 것을 의미하며, 즉 다른 인스턴스멤버들도 모두 존재하기 때문이다.

⚠️ **GitHub.com Fallback** ⚠️