자바의 정석 ch06. 객체지향 프로그래밍(1)

1. 객체지향언어

  • 객체지향이론의 기본 개념: 실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물간의 상호작용

  • 객체지향언어의 주요특징
    1. 코드의 재사용성이 높다.
    2. 코드의 관리가 용이하다.
    3. 신뢰성이 높은 프로그래밍을 가능하게 한다.


2. 클래스와 객체

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

  • 클래스: 객체를 정의해놓은 것. 또는 객체의 설계도 또는 틀
  • 객체: 실제로 존재하는 것. 사물과 같은 유형적인 것뿐만 아니라, 개념이나 논리와 같은 무형적인 것들도 객체로 간주.
  • 클래스-객체 관계 비유 (RPG게임)
    클래스: 직업(마법사, 전사, 궁수...)
    객체: 캐릭터

→ 클래스는 객체를 생성하는데 사용되며, 객체는 클래스에 정의된 대로 생성됨.

객체와 인스턴스

  • 클래스의 인스턴스화: 클래스로부터 객체를 만드는 과정
  • 클래스의 인스턴스: 어떤 클래스로부터 만들어진 객체
  • 객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖고있으며, 인스턴스는 어떤 클래스로부터 만들어진 것인지를 강조하는 보다 구체적인 의미를 갖고 있다.
  • 클래스 ─(인스턴스화)→ 인스턴스(객체)

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

  • 객체는 다수의 속성과 다수의 기능을 갖는다. 즉, 객체는 속성와 기능의 집합이라고 할 수 있다.
  • 속성: 멤버변수, 특성, 필드, 상태
  • 기능: 메서드, 함수, 행위

인스턴스의 생성과 사용

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

Magician magic;
magic = new Magician();
class Magician {
	//마법사의 속성(멤버변수)
    String hair; //머리 색상
    int level; //레벨
    int energy; //체력
    
    //마법사의 기능(메서드)
    void healing() { ++energy; } //체력회복 기술을 쓰는 메서드
 }
 
 class MagicianTest {
 	public static void main(String args[]) {
    		Magician magic; //Magician인스턴스를 참조하기 위한 변수 magic선언(아이디가 magic인 캐릭터 생성)
        	magic = new Magician(); //Magician인스턴스를 생성한다.
        	magic.level = 9; //Magician인스턴스의 멤버변수 level값을 9로 한다.
        	magic.healing(); //Magician인스턴스의 메서드 healing()을 호출한다.
        	System.out.println("현재 캐릭터의 레벨은" + m.level + "입니다.");
        	//현재 캐릭터의 레벨은 9입니다.
        }
 }
  • 인스턴스는 참조변수를 통해서만 다룰 수 있으며, 참조변수의 타입은 인스턴스의 타입과 일치해야한다.
  • 같은 클래스로부터 생성되었을지라도 각 인스턴스의 속성(멤버변수)은 서로 다른 값을 유지할 수 있으며, 메서드의 내용은 모든 인스턴스에서 동일하다.
  • 참조변수에는 하나의 값(주소)만이 저장될 수 있으므로 둘 이상의 참조변수가 하나의 인스턴스를 가리키는 것은 가능하지만 하나의 참조변수로 여러 개의 인스턴스를 가리키는 것은 가능하지 않다.
  • 인스턴스와 참조변수의 관계 비유
    : 해당 마법사 캐릭터(인스턴스)는 해당 계정(ID)을 통해서만 다룰 수 있다. 이처럼 인스턴스는 오직 참조변수를 통해서만 다룰 수 있다.

객체 배열

  • 객체 배열 안에 객체가 저장되는 것이 아닌, 객체의 주소가 저장된다. 즉, 객체 배열은 참조변수들을 하나로 묶은 참조변수 배열인 것이다.
  • 반드시 객체를 생성해서 객체 배열의 각 요소에 저장을 해야한다.
//첫번째 방법
Tv[] tvArr = new Tv[3];

tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();

//두번째 방법
Tv[] tvArr = new Tv(100);

for (int i = 0; i < tvArr.length; i++) {
	tvArr[i] = new Tv();
}
  • 객체 배열도 같은 타입의 객체만 저장할 수 있다. (단, '다형성'을 통해 여러 종류의 객체를 다룰 수 있다.)

클래스의 또 다른 정의

  • 데이터와 함수의 결합(구조체+함수)
  • 사용자정의 타입(자료형 외에 프로그래머가 서로 관련된 변수들을 묶어서 하나의 타입으로 새로 추가하는 것)
    ex. 시, 분, 초를 저장하기 위한 세 변수를 멤버변수로 갖는 Time클래스를 정의
class Time {
	
    int hour;
    int minute;
    float second;
}



3. 변수와 메서드

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

<클래스 영역>

  • 인스턴스변수
    : 멤버변수 중 static이 붙지 않은 것
    : 독립적인 저장공간을 가지므로 서로 다른 값을 가질 수 있다.

  • 클래스변수
    : 멤버변수 중 static이 붙은 것
    : 모든 인스턴스가 공통된 저장공간(변수)을 공유한다. 따라서 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야하는 속성을 가진다.

<클래스 영역 이외의 영역>

  • 지역변수
    : 멤버변수를 제외한 나머지 변수들
    : 메서드 내에 선언되어 메서드 내에서만 사용 가능하며, 메서드가 종료되면 소멸되어 사용할 수 없게 된다.
class Variables {
	
    //클래스 영역
	int iv; //인스턴스 변수
 	static int cv; //클래스 변수
    
    void method() {
    //메서드 영역
    	int lv = 0; //지역변수
    }
}
    
변수의 종류선언위치생성시기
클래스 변수클래스 영역클래스가 메모리에 올라갈 때
인스턴스 변수클래스 영역인스턴스가 생성되었을 때
지역변수클래스 영역 이외의 영역(메서드, 생성자, 초기화 블럭 내부)변수 선언문이 수행되었을 때

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

class Card {
	
    //인스턴스변수(무늬, 숫자): 자신만의 무늬와 숫자 유지
	String kind;
    	int number;
        
   //클래스변수(폭, 넓이): 모든 카드가 같은 값을 유지
   	static int width = 100;
    	static int height = 250;
}
  • 인스턴스변수는 인스턴스가 생성될 때마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유하므로 항상 공통된 값을 갖는다.

메서드

  • 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것
  • 수학의 함수와 유사
  • 장점
    1. 높은 재사용성
    2. 중복된 코드의 제거
    3. 프로그램의 구조화

메서드의 선언과 구현

  • 메서드는 크게 '선언부'와 '구현부'로 이루어져 있다.
int add(int a, int b) //선언부
{ 	//구현부
	int result = a + b;
    	return result;
}
  • 메서드의 선언부: 메서드의 이름, 매개변수 선언, 변환타입(출력)으로 구성
  • 메서드의 구현부: 메서드의 선언부 다음에 오는 괄호{}에 메서드를 호출했을 때 수행될 문장들 넣기

메서드의 호출

메서드이름(값1, 값2,..)
  • 인자의 개수와 순서는 호출된 메서드에 선언된 매개변수와 일치
  • 같은 클래스 내의 메서드끼리는 참조변수를 사용하지 않고도 서로 호출이 가능하지만 static 메서드는 같은 클래스 내의 인스턴스 메서드를 호출할 수 없다.

return문

  • 반환 타입이 void면 생략가능

JVM의 메모리구조

1. 메서드 영역

클래스 파일을 읽어서 분석하여 클래스에 대한 정보(클래스 데이터)를 이곳에 저장한다. 이 떄, 클래스변수도 이 영역에 함께 생성된다.

2. 힙

인스턴스가 생성되는 공간. 인스턴스변수들이 생성되는 공간.

3. 호출스택

메서드 작업에 필요한 메모리 공간을 제공한다.

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

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

자바에서는 메서드를 호출할 때 매개변수로 지정한 값을 메서드의 매개변수에 복사해서 넘겨준다.

  • 기본형 매개변수: 기본형 값이 복사. 변수의 값을 읽기만 할 수 있다.
  • 참조형 매개변수: 인스턴스의 주소가 복사. 변수의 값을 읽고 변경할 수 있다.

재귀호출

  • 메서드의 내부에서 메서드 자신을 다시 호출하는 것
void method() {
	method(); //재귀호출. 메서드 자신을 호출한다
}

클래스 메서드와 인스턴스 메서드

  • 클래스 메서드는 객체를 생성하지 않고도 '클래스이름.메서드이름(매개변수'와 같은 식으로 호출이 가능하나, 인스턴스 메서드는 반드시 객체를 생성해야만 호출할 수 있다.
  • 인스턴스 메서드는 인스턴스 변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드이다.
  • 클래스 메서드는 인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드를 사용하지 않는) 메서드를 클래스 메서드라고 정의한다.
  1. 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통적으로 사용해야하는 것에 static을 붙인다.
  2. 클래스 변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
  3. 클래스 메서드는 인스턴스 변수를 사용할 수 없다. 인스턴스 변수는 인스턴스가 반드시 존재해야만 사용할 수 있기 때문이다.
  4. 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.

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

같은 클래스에 속한 멤버들 간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출이 가능하다. 단, 클래스멤버가 인스턴스 멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다. 왜냐하면 인스턴스 멤버가 존재하는 시점에 클래스 멤버는 항상 존재하지만, 클래스멤버가 존재하는 시점에 인스턴스 멤버가 존재하지 않을 수도 있기 때문이다.



4. 오버로딩

  • (메서드) 오버로딩 : 한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것
  • 오버로딩 조건
    1. 메서드 이름이 같아야 한다.
    2. 매개변수의 개수 또는 타입이 달라야 한다. (반환 타입은 오버로딩을 구현하는데 아무런 영향을 주지 못한다.)
  • ex. println메서드 : 호출할 때 매개변수로 지정하는 타입에 따라서 호출되는 println메서드가 달라진다.
  • ex.
long add(int a, long b) {
	return a + b;
}
long add(long a, int b) {
	return a + b;
}
  • 오버로딩의 장점
    여러 메서드들을 하나의 이름으로 정의될 수 있음. 이를 통해 이 메서드들은 이름이 같으니, 같은 기능을 하겠다고 예측 가능.

가변인자와 오버로딩

기존에는 메서드의 매개변수 개수가 고정적이었으나, JDK1.5부터 동적으로 지정해줄 수 있게 되었으며, 이 기능을 '가변인자'라고 한다. 가변인자 외에도 매개변수가 더 있다면 가변인자를 제일 마지막에 선언해야한다.

//가변인자는 '타입... 변수명'과 같은 형식으로 선언
public PrintStream printf(String format, /*가변인자:*/Object... args) {...}



5. 생성자

  • 생성자: 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'이다.
  • 생성자 비유
    캐릭터를 생성할 때 세부사항을 고르는 것(성별, 머리색 등)
  • 생성자 조건
    1. 생성자의 이름은 클래스의 이름과 같아야 한다.
    2. 생성자는 리턴값이 없다.
class Card {
	Card() {	//매개변수가 없는 생성자
    	//...
    }
    
    Card(String k, int num) {	//매개변수가 있는 생성자
    	//...
    }
  • 연산자 new가 인스턴스를 생성하는 것. 생성자가 인스턴스를 생성하는 것이 아님.

기본 생성자

  • 클래스에 생성자를 정의하지 않고도 인스턴스를 생성할 수 있게 해줌.
  • 컴파일 할 때, 소스파일의 클래스에 생성자가 하나도 정의되지 않은 경우 컴파일러는 자동적으로 아래와 같은 내용의 기본 생성자를 추가하여 컴파일을 한다.
클래스 이름() { }
Card() { }
  • 기본 생성자가 컴파일러에 의해서 추가되는 경우는 클래스에 정의된 생성자가 하나도 없을 때 뿐이다.

매개변수가 있는 생성자

Magician m = new Magician ();
m.hair = "white";
m.gender = "female";

Magician m = new Magician("white, "female");


생성자에서 다른 생성자 호출하기 - this(), this

  • 생성자의 이름으로 클래스이름 대신 this를 사용한다.
  • 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.



6. 변수의 초기화

  • 변수를 선언하고 처음으로 값을 저장하는 것
  • 멤버변수(클래스변수, 인스턴스변수)는 초기화를 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지므로 초기화하지 않고 사용해도 됨. 하지만 지역변수는 사용하기 전에 반드시 초기화해야함.
  • 멤버변수의 초기화 방법
    1. 명시적 초기화
    : 변수를 선언과 동시에 초기화하는 것
    2. 생성자
    3. 초기화 블럭(클래스 초기화 블럭/인스턴스 초기화 블럭)
    : 클래스 초기화 블럭 - 클래스가 메모리에 처음 로딩될 때 한번만 수행
    : 인스턴스 초기화 블럭 - 생성자와 같이 인스턴스를 생성할 때 마다 수행
    : 생성자보다 인스턴스 초기화 블럭이 먼저 수행됨



객체지향 예제

[연습문제 참고]

다음과 같이 정의된 메서드를 작성하고 테스트하시오.
메서드명 : Ascending
기능: 주어진 배열에 담긴 값을 오름차순으로 정렬한다. (for문 사용)
반환타입 : int[]
매개변수 : int[]arr - 정수값이 담긴 배열

class Exercise6_20
{
	/*
	(1) Ascending 메서드를 작성하시오
    	public static int[] Ascending(int[] arr) {
		if (arr == null || arr.length == 0)
			return arr;
		
        	for (int i = 0 ; i < arr.length; i++) {
			for (int j = i + 1; j < arr.length; j++) {
				if (arr[i] > arr[j]) {
					int tmp = arr[i];
					arr[i] = arr[j];
					arr[j] = tmp;
				}
			}
				
		}
    
		return arr;
	}

	*/

	public static void main(String[] args)
	{
		int[] original = {3, 2, 1, 5, 8, 6, 9, 7, 4};
		System.out.println(java.util.Arrays.toString(original));
        
		int[] result = Ascending(original);
		System.out.println(java.util.Arrays.toString(result));
	}
}

좋은 웹페이지 즐겨찾기