1. 객체지향 언어


  • 객제지향 언어 = 프로그래밍 언어 + 객체지향 개념(규칙)

핵심 개념

  1. 캡슐화
  2. 상속
  3. 추상화
  4. 다형성

객체지향 프로그래밍

  • 특징
    • 다형성
    • 정보 은닉
    • 추상화
    • 캡슐화
  • 장점
    • 유지보수의 용이
    • 복잡한 대형 프로그램 작성 가능

2~4. 클래스와 객체


클래스

  • 정의 - 객체를 정의해 놓은 것
  • 용도 - 객체를 생성하는데 사용
  • 개념
    • 객체를 생성하기 위한 설계도 혹은 틀
    • 연관되어 있는 변수와 메서드의 집합

객체

  • 정의 - 실제로 존재하는 것. 사물 또는 개념
  • 용도 - 객체가 가지고 있는 기능과 속성에 따라 다름
  • 개념
    • 클래스의 인스턴스화 : 클래스로부터 객체를 만드는 과정
    • 클래스의 타입으로 선언되었을 경우 객체
    • 클래스에 선언된 그대로 소프트웨어 상에 설계도로 구현한 대상
  • 특징
    • “클래스의 인스턴스” 라고도 불림
    • OOP관점에서 클래스의 타입으로 선언되었을 때 객체라고 부름

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

  • 객체 = 속성(변수) + 기능(메서드)
class Tv {
	// 속성(변수)
	String color;
	boolean power;
	int channel;
	// 기능(메서드)
	void power() {
		power = !power;
	}
	void channelUp() {
		channel++;
	}
	void channelDown() {
		channel--;
	}
}

인스턴스

  • 객체 : 모든 인스턴스를 대표하는 일반적 용어

  • 인스턴스 : 특정 클래스로부터 생성된 객체(예:Tv인스턴스)

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

  • 개념

    • 클래스의 인스턴스 : 클래스로부터 만들어진 객체
    • 객체가 메모리에 할당되어 실제 사용될 때 인스턴스
    • 설계도를 바탕으로 소프트웨어 상에 구현된 실체
      • 즉, 객체를 소프트웨어 상에 실체화
      • 실체화된 인스턴스는 메모리에 할당됨
  • 특징

    • OOP관점에서 객체가 메모리에 할당되어 실제 사용될 때 인스턴스라고 부름
    • 인스턴스는 어떤 원본(추상적인 개념)으로부터 생성된 복제본을 의미
    • 추성적인 개념과 구체적인 객체 사이의 관계에 초점을 맞출 경우에 사용
      • 객체는 클래스의 인스턴스
      • 실행 프로세스는 프로그램의 인스턴스

예시

/* 클래스 */
public class Animal {
  ...
}
/* 객체와 인스턴스 */
public class Main {
  public static void main(String[] args) {
    Animal cat, dog; // 클래스의 타입으로 '객체' 선언
    // 인스턴스화
    cat = new Animal(); // cat은 Animal 클래스의 '인스턴스'(객체를 메모리에 할당)
    dog = new Animal(); // dog은 Animal 클래스의 '인스턴스'(객체를 메모리에 할당)
		Animal rat = new Animal();
		// 참조변수 rat 은 Animal 인스턴스를 가리키고 있다.
		// 인스턴스는 오직 참조변수를 통해서만 다룰 수 있다.
  }
}

6~7. 객체의 생성과 사용


1. 객체의 생성

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

2. 객체의 사용

t.channel = 7;   // Tv인스턴스의 멤버변수 channel의 값을 7로 설정
t.channelDown(); // Tv인스턴스의 메서드 channelDown()을 호출
System.out.println("현재 채널은 " + t.channel + " 입니다.");
  • 하나의 인스턴스를 여러 개의 참조변수가 가리키는 경우 (가능)
  • 여러 개의 인스턴스를 하나의 참조변수가 가리키는 경우 (불가능)

8. 객체배열


  • 객체 배열 == 참조변수 배열
Tv t1, t2, t3;
Tv[] tvArr = new Tv[3]; // 길이가 3인 Tv타입 참조변수 배열
// 객체를 생성해서 배열의 각 요소에 저장
tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();

9~10. 클래스의 정의


  • 클래스 == 데이터 + 함수
  1. 변수 - 하나의 데이터를 저장할 수 있는 공간
  2. 배열 - 같은 종류의 여러 데이터를 하나로 저장할 수 있는 공간
  3. 구조체 - 서로 관련된 여러 데이터(종류 관계X)를 하나로 저장할 수 있는 공간
  4. 클래스 - 데이터와 함수의 결합(구조체 + 함수)
  • 사용자 정의 타입 - 원하는 타입을 직접 만들 수 있다.
// 시간을 나타내고 싶은 타입이 없을 경우
class Time {
	int hour;
	int minute;
	int second;
}
Time t = new Time();

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


class Variables {
	// 클래스 영역
	// 선언문만 가능 (변수 선언, 메서드 선언)
	int iv;        // 인스턴스 변수
	static int cv; // 클래스 변수(static변수, 공유변수)
	void method() {
		// 메서드 영역
		int lv = 0;  // 지역변수
	}
}
변수의 종류선언위치생성시기
클래스 변수 (class variable)클래스 영역클래스가 메모리에 올라갈 때 (프로그램을 실행했을 때)
인스턴스 변수 (instance variable)클래스 영역인스턴스가 생성되었을 때
지역변수 (local variable)클래스 영역 이외의 영역 (메서드, 생성자, 초기화 블럭 내부)변수 선언문이 수행되었을 때

12~13. 클래스 변수와 인스턴스 변수


멤버변수 : 클래스 영역에 선언된 변수

  • 인스턴스 변수
    • 클래스의 인스턴스를 생성할 때 만들어짐
    • 인스턴스마다 고유한 값을 가짐
  • 클래스 변수 (static 변수)
    • 모든 인스턴스가 공통으로 공유 (공통된 메모리 공간을 참조)
    • 객체 생성 없이 사용 가능
class Card {
	// 인스턴스 변수 (개별 속성)
	String kind; // 무늬
	int number;  // 숫자
	// 클래스 변수 (공통 속성)
	static int width = 100;  // 폭
	static int height = 250; // 높이
}
// 객체 생성
Card c = new Card();
// 인스턴스 변수 설정
c.kind = "HEART";
c.number = 5;
// 클래스 변수 수정 시 클래스.cv 로 작성
Card.width = 200;
Card.height = 300;

14~16. 메서드란?


함수와 메서드의 차이

  • 함수 Function
    • 특정 작업을 수행하는 코드조각
    • 독립된 기능을 수행하는 단위
    • 클래스로부터 독립적
  • 메서드 Method
    • 클래스, 구조체, 열거형에 포함되어 있는 함수
    • 다른말로 클래스 함수

14. 메서드란?

  1. 문장들을 묶어놓은 것.
    • 작업단위로 문장들을 묶어서 이름 붙인 것
  2. 값(입력)을 받아서 처리하고, 결과를 반환(출력)
  • 메서드의 장점
    • 코드의 중복을 줄일 수 있음
    • 코드의 관리가 쉬움
    • 코드를 재사용할 수 있음
    • 코드가 간결해서 이해하기 쉬워짐
  • 메서드의 작성
    • 반복적으로 수행되는 여러 문장을 메서드로 작성
    • 하나의 메서드는 한 가지 기능만 수행하도록 작성
  • 메서드 = 선언부 + 구현부
// 선언부
int add (int a, int b) {
	// 구현부
	int result = a + b;
	return result;
}

15. 메서드의 구현부

  • 지역변수(lv) : 메서드 내에 선언된 변수
// 메서드 영역
int add (int a, int b) {
	// a, b 는 매개변수
	// a, b, result 는 지역변수
	int result = a + b;
	return result;
}
// 메서드 영역
int multiply (int a, int b) {
	// a, b 는 매개변수
	// a, b, result 는 지역변수
	int result = a * b;
	return result;
}

17~19. 메서드호출


public class ArgumentParameter {
 
	public static void main(String[] args) {
		int argument = 10;		
		operation(argument); 	// 전달인자(Argument, 원본)
	}
	
	private static int operation(int parameter){ // 매개변수(Parameter, 복사본)
		parameter += 10;
		return parameter;
	}
}

Call by value

  • 함수에 전달되는 데이터 타입이 Primitive 일 경우
  • 함수가 호출될 때, 함수를 위한 임의의 메모리 공간이 생성됨
  • Call by value 방식으로 호출 시 전달되는 변수의 값을 복사하여 함수의 인자로 전달함
  • 복사된 인자는 함수 안에서 지역적으로 사용되는 local value의 특성을 가짐
  • 즉, 함수 안에서 인자의 값(Parameter)이 변경되어도, 외부 변수의 값(Argument)은 변경 X

Call by reference

  • 함수에 전달되는 데이터 타입이 Reference 일 경우
  • Call by reference 방식으로 호출 시 전달되는 변수의 번지수를 전달함
  • Argument 와 parameter 모두 같은 객체를 참조하게 됨
  • 즉, 함수 안에서 인자의 값이 변경되면, 외부 변수의 값도 변경됨

22. 호출 스택(call stack)


  • 메서드 수행에 필요한 메모리가 제공되는 공간
  • 메서드가 호출되면 호출스택에 메모리 할당, 종료되면 해제

23. 기본형 매개변수


  • 기본형 매개변수 - 변수의 값을 읽기만 할 수 있다. (read only)
  • 참조형 매개변수 - 변수의 값을 읽고 변경할 수 있다. (read & write)
class Data {
	int x;
}
 
public class Ex6_6 {
	public static void main(String[] args) {
		Data d = new Data();
		d.x = 10; // Data객체의 인스턴스 변수 초기화
		System.out.println("main() : x = " + d.x);
		change(d.x); // argument로 Data객체의 x를 준다.
		System.out.println("After change(d.x)");
		// 메서드 안에서는 d.x 와 같은 기본형 값을 리터럴로 사용했기 때문에 변함이 없음
		System.out.println("main() : x = " + d.x);
	}
	static void change(int x) { // parameter로 Data객체의 x를 받지만 기본형은 리터럴로 전달
		x = 1000; // 리터럴 x 를 1000 으로 변경
		System.out.println("change() : x = " + x);
	}
}

24~25. 참조형 매개변수


  • 기본형 매개변수 - 변수의 값을 읽기만 할 수 있다. (read only)
  • 참조형 매개변수 - 변수의 값을 읽고 변경할 수 있다. (read & write)
class Data2 {
	int x;
}
 
public class Ex6_7 {
	public static void main(String[] args) {
		Data2 d = new Data2();
		d.x = 10; // Data2객체의 인스턴스 변수 x를 초기화
		System.out.println("main() : x = " + d.x);
		change(d);
		System.out.println("After change(d.x)");
		// 메서드가 객체를 참조하여 인스턴스 변수를 수정했기 때문에 변경사항이 생김
		System.out.println("main() : x = " + d.x);
	}
	static void change(Data2 d) { // parameter로 참조형 Data2객체를 받음
		d.x = 1000; // d객체의 인스턴스 변수를 직접 변경
		System.out.println("change() : x = " + d.x);
	}
}

26~29. static 메서드, 인스턴스 메서드


인스턴스 메서드

  • 인스턴스 생성 후, ‘참조변수.메서드이름()’ 으로 호출
  • 인스턴스 멤버(iv, im)와 관련된 작업을 하는 메서드
  • 메서드 내에서 인스턴스 변수(iv) 사용 가능

static 메서드

  • 객체 생성 없이 ‘클래스이름.메서드이름()’ 으로 호출
  • 인스턴스 멤버(iv, im)와 관련없는 작업을 하는 메서드
  • 메서드 내에서 인스턴스 변수(iv) 사용 불가
  • 작성한 메서드 중 인스턴스 변수나 인스턴스 메서드를 사용하지 않는다면 static

30~31. 오버로딩(overloading)


  • 한 클래스 안에 같은 이름의 메서드 여러 개 정의하는 것

오버로딩이 성립하기 위한 조건

  1. 메서드 이름이 같아야 한다.
  2. 매개변수의 개수 또는 타입이 달라야 한다.
  3. 반환 타입은 영향없다.
// 틀린 예시
// 반환 타입만 다르기 때문에 오버로딩이 아님 (중복 정의)
int add(int a, int b) {
	return a + b;
}
long add(int a, int b) {
	return (long)(a + b);
}
// 올바른 예시
// 매개변수의 타입이 다르기 때문에 오버로딩
long add(int a, long b) {
	return a + b;
}
long add(long a, int b) {
	return a + b;
}

오버로딩의 올바른 예 - 매개변수는 다르지만 같은 의미의 기능수행

class MyMath3 {
	int add(int a, int b) {
		System.out.println("int add(int a, int b) - ");
		return a + b;
	}
	long add(long a, long b) {
		System.out.println("long add(long a, long b) - ");
		return a + b;
	}
	int add(int[] a) {
		System.out.println("int add(int[] a) - ");
		int result = 0;
		for (int i = 0; i < a.length; i++) {
			result += a[i];
		}
		return result;
	}
}

32~35. 생성자, 기본 생성자


생성자 (constructor)

Time t = new Time();
t.hour = 12;
t.minute = 34;
t.second = 56;
Time t = new Time(12,34,56);
  • 개념
    • 인스턴스가 생성될 때마다 호출되는 ‘인스턴스 초기화 메서드’
    • 인스턴스 생성 시 수행 할 작업(iv 초기화)에 사용
클래스이름(타입 변수명, 타입 변수명, ...) {
	// 인스턴스 생성 시 수행될 코드
	// 주로 인스턴스 변수의 초기화 코드를 적는다.
}
 
class Card {
	Card() { // 매개변수 없는 생성자
		// 인스턴스 초기화 작업
	}
	Card(String kind, int number) { // 매개변수 없는 생성자
		// 인스턴스 초기화 작업
	}
}
  • 특징
    • 이름이 클래스 이름과 같아야 한다.
    • 리턴값이 없다. (void 안 붙임)
    • 모든 클래스는 반드시 생성자를 가져야 한다.

기본 생성자 (default constructor)

class Data_1 {
	int value;
}
 
class Data_2 {
	int value;
	
	Data_2(int x) { // 매개변수가 있는 생성자
		value = x;
	}
}
 
public class Ex6_11 {
	public static void main(String[] args) {
		Data_1 d1 = new Data_1();
		Data_2 d2 = new Data_2(); // compile error 발생
	}
}
  • 개념
    • 매개변수가 없는 생성자
    • 생성자가 하나도 없을 때만, 컴파일러가 자동 추가

매개변수가 있는 생성자

class Car {
	String color;
	String gearType;
	int door;
	Car() {} // 기본 생성자
	Car(String c, String g, int d) { // 매개변수가 있는 생성자
		color = c;
		gearType = g;
		door = d;
	}
}
Car c = new Car();
c.color = "white";
c.gearType = "auto";
c.door = 4;
Car c = new Car("white", "auto", 4);

36~37. 생성자 this(), 참조변수 this


생성자 this()

class Car2 {
	String color;
	String gearType;
	int door;
	Car2() {
		this("white", "auto", 4);
	}
	Car2(String color) {
		this(color, "auto", 4);
	}
	Car2(String color) {
		door = 5; // 첫 줄에 쓰지 않아서 에러
		Car(color, "auto", 4); // this를 쓰지 않아서 에러
	}
	Car2(String color, String gearType, int door) {
		this.color = color;
		this.gearType = gearType;
		this.door = door;
	}
}
  • 개념
    • 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용한다.
  • 특징
    • 다른 생성자 호출 시 첫 줄에서만 사용가능

참조변수 this

class Car2 {
	String color;
	String gearType;
	int door;
	Car2(String color, String gearType, int door) {
		// this.color는 iv, color는 lv
		this.color = color;
		this.gearType = gearType;
		this.door = door;
	}
}
  • 개념
    • 인스턴스 자신을 가리키는 참조변수, 인스턴스의 주소가 저장되어 있다.
    • 모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재한다.
  • 특징
    • 인스턴스 메서드(생성자 포함)에서 사용가능 (왜? this 는 인스턴스 변수를 의미하기 때문에)
    • 지역변수(lv)와 인스턴스 변수(iv)를 구별할 때 사용

38~41. 변수, 멤버변수의 초기화


변수의 초기화

class InitTest {
	// 자동 초기화
	// 유지 기간이 비교적 길기 때문에 자동 초기화
	int x;       // 인스턴스 변수
	int y = x;   // 인스턴스 변수
	void method1() {
		// 수동 초기화
		// 호출 스택 메모리는 재사용이 빈번하기 매번 자동 초기화 시 성능이 저하됨
		// 지역변수는 메서드가 호출되서 작업하는 동안만 존재하기 때문에 생명 주기가 짧음
		int i;     // 지역변수
		int j = i; // 에러. 지역변수를 초기화하지 않고 사용
	}
}
  • 개념
    • 지역변수(lv)는 수동 초기화 해야함 (사용 전 꼭!!!)
    • 멤버변수(iv, cv)는 자동 초기화된다.

멤버변수의 초기화

  • 클래스 변수 초기화 시점 : 클래스가 처음 로딩될 때 단 한 번
  • 인스턴스 변수 초기화 시점 : 인스턴스가 생성될 때 마다
  1. 명시적 초기화(=) (간단한 초기화)
class Car {
	int door = 4;            // 기본형(primitive type) 변수의 초기화
	Engine e = new Engine(); // 참조형(reference type) 변수의 초기화
}
  1. 초기화 블럭 (복잡한 초기화)
    • 인스턴스 초기화 블럭: { }
    • 클래스 초기화 블럭: static { }
class StaticBlockTest {
	static int[] arr = new int[10]; // 명시적 초기화
	static { // 클래스 초기화 블럭 - 배열 arr을 난수로 채운다.
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int)(Math.random() * 10) + 1;
		}
	}
}
  1. 생성자 (복잡한 초기화)
Car(String color, String gearType, int door) { // 매개변수있는 생성자
	this.color = color;
	this.gearType = gearType;
	this.door = door;
}