[자바의 정석 기초편] 객체지향개념 1

JEREGIM·2023년 1월 16일
0

📌클래스와 객체

클래스의 정의 : 클래스란 객체를 정의해 놓은 것
클래스의 용도 : 클래스는 객체를 생성하는데 사용

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

클래스객체
제품 설계도제품
TV 설계도TV

Q&A

Q. 클래스(설계도)가 왜 필요한가?
A. 객체(제품)를 생성하기 위해서

Q. 객체가 왜 필요한가?
A. 객체를 사용하기 위해서

Q. 객체를 사용한다는 것은?
A. 객체가 가진 속성과 기능을 사용하려고


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

객체 = 속성(변수) + 기능(메서드)

TV의 속성 : 크기, 길이, 색상, 전원상태, 채널 등
TV의 기능 : 켜기, 끄기, 채널 변경하기 등

class Tv {
	String color; // 색상
    boolean power; // 전원상태
    int channel; // 채널
    
    void power() { power = !power; } 
    void channelUp() { channel++; }
    void channelDown() { channel--; }
}
  • color, power, channel 은 변수
  • power(), channelUp(), channelDown() 은 메서드

📌객체와 인스턴스

객체 : 모든 인스턴스를 대표하는 일반적 용어
인스턴스 : 특정 클래스로부터 생성된 객체(예 : Tv인스턴스)


📌하나의 소스파일에 여러 클래스 작성

public class가 있는 경우, 소스파일의 이름은 반드시 public class의 이름과 일치해야 한다.
1. 하나의 소스파일에 둘 이상의 public class가 존재하면 안된다.
2. 이름은 대소문자를 구분한다.


📌객체의 생성과 사용

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

t.channel = 7; // Tv 인스턴스의 멤버변수 channel 값을 7로 한다. 
t.channelDown(); // Tv 인스턴스의 메서드를 호출

  • 참조변수 t는 리모콘 역할, 객체를 가르키는 주소를 저장한다.
  • 참조변수가 없으면 객체는 사용 불가
  • 사용되지 않는 객체는 GC(가비지 컬렉터)가 자동으로 객체를 없애준다.

  • 그림(a)는 가능
  • 그림(b)는 불가능 -> 변수에는 하나의 값만 저장 가능하기 때문에

📌객체 배열

객체 배열 == 참조변수 배열

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

  • Tv[3] 객체 배열은 Tv타입 참조변수가 3개 만들어진 것이다.
  • 결국 객체 배열은 참조변수 배열이다.
  • 참조변수 배열을 생성한 후, 각 참조변수에 객체를 따로 생성해줘야 한다.

📌클래스의 정의

클래스

1. 설계도

2. 데이터 + 함수

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

3. 사용자 정의 타입 - 원하는 타입을 직접 만들 수 있다.

int hour = 12;                  class Time {
int minute = 34;	   ->			int hour;
int second = 56; 					int minute;
									int second;
								}
          
								Time t = new Time();
								t.hour = 12;
								t.minute = 34;
								t.second = 56;
  • 오른쪽 코드가 객체지향적인 코드이다.

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

class Variables
{
	int iv;         // 인스턴스 변수
    static int cv;  // 클래스 변수(static변수, 공유변수)
    
    void method()
    {
    	int lv = 0; // 지역변수
    }
}    
변수의 종류선언위치생성시기
클래스 변수(class variable)클래스 영역클래스가 메모리에 올라갈 때
인스턴스 변수(instance variable)클래스 영역인스턴스가 생성되었을 때
지역변수(local variable)클래스 영역 이외의 영역(메서드, 생성자, 초기화 블럭 내부)변수 선언문이 수행되었을 때
  • 지역변수(lv)는 메서드 종료시 자동 제거
  • 지역변수(lv)는 메서드 영역 안에서만 사용 가능
  • 클래스 변수(cv)는 앞에 static을 붙인다.
  • 클래스 변수(cv)는 아무때나 사용 가능
  • 객체는 iv를 묶어놓은 것

각 변수들의 저장 공간


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

class Card {
	String kind; // 무늬
    int number; // 숫자
    
    static int width  = 100; // 폭
    static int height = 250; // 높이
}
  • 카드의 무늬와 숫자는 각각 달라야 하는 개별 속성이기 때문에 인스턴스 변수(iv)를 사용
  • 카드의 폭과 높이는 모두 같아야 하는 공통 속성이기 때문에 클래스 변수(cv)를 사용
Card c = new Card();
c.kind = "HEART";
c.number = 5;

Card.width = 200; // 클래스 변수는 앞에 참조변수 대신 클래스 이름을 붙여준다.
Card.height = 300;
  • 클래스 변수는 앞에 참조변수 대신 클래스 이름을 붙여준다.
  • 클래스 변수는 객체 생성 없이 사용 가능, 자동으로 만들어짐

📌메서드

- 문장들을 묶어놓은 것
- 값(입력)을 받아서 처리하고, 결과를 반환(출력)

메서드의 장점

  • 코드의 중복을 줄일 수 있다.
  • 코드의 관리가 쉽다.
  • 코드를 재사용할 수 있다.
  • 코드가 간결해서 이해하기 쉬워진다.

메서드의 작성

  • 반복적으로 수행되는 여러 문장을 메서드로 작성
  • 하나의 메서드는 한 가지 기능한 수행하도록 작성
  • 반환값이 없으면 반환 타입은 void로 적는다.

메서드의 구현부

  • 지역변수(lv) : 메서드 내에 선언된 변수
int add(int x, int y) {
	int result = x + y;
    return result;
}    
  • x, y 는 매개변수(입력)
  • x, y, result 모두 지역변수

return 문

  • return 문 : 실행 중인 메서드를 종료하고 호출한 곳으로 되돌아간다.
  • 반환 타입이 void일 경우 return 문 생략 가능
  • 반환 타입이 void가 아닌 경우, 반드시 return 문 작성해줘야 한다.
int max(int a, int b) {
	if(a > b) 
    	return a;
    else
    	return b;
}
  • 조건식이 참 또는 거짓일 때의 return 문을 모두 작성해줘야 한다.

반환값

  • 반환값은 반환 타입과 일치(자동형변환)해야 한다.

📌호출 스택(call stack)

스택(stack) : 밑이 막힌 상자, 위에 차곡차곡 쌓인다.

  • 3번에서 main은 대기 상태, println 실행 상태
  • 하나의 스택에서는 하나의 메서드만 실행된다.

호출 스택(call stack)

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

📌기본형 매개변수

기본형 매개변수 : 변수의 값을 읽기만 할 수 있다.(read only)

class Data { int x; }

class Ex6_6 {
	public static void main(String[] args) {
		Data d = new Data();
		d.x = 10;
		System.out.println("main() : x = " + d.x);

		change(d.x);
		System.out.println("After change(d.x)");
		System.out.println("main() : x = " + d.x);
	}

	static void change(int x) {  // 기본형 매개변수 x
		x = 1000; // change() 메서드의 지역변수로 종료 시 제거된다.
		System.out.println("change() : x = " + x);
	}
}

결과
main() : x = 10
change() : x = 1000
After change(d.x)
main() : x = 10


📌참조형 매개변수

참조형 매개변수 : 변수의 값을 읽고 변경할 수 있다.(read & write)

class Data2 { int x; }

class Ex6_6 {
	public static void main(String[] args) {
		Data2 d = new Data2();
		d.x = 10;
		System.out.println("main() : x = " + d.x);

		change(d);
		System.out.println("After change(d)");
		System.out.println("main() : x = " + d.x);
	}

	static void change(Data2 d) {  // 참조형 매개변수 d
		d.x = 1000;
		System.out.println("change() : x = " + d.x);
	}
}

결과
main() : x = 10
change() : x = 1000
After change(d)
main() : x = 1000


📌참조형 반환타입

class Data3 {int x;}

public class Ex6_3 {
    public static void main(String[] args) {
        Data3 d = new Data3();
        d.x = 10;

        Data3 d2 = copy(d);
        System.out.println("d.x = "+d.x);
        System.out.println("d2.x = "+d2.x);
    }

    static Data3 copy(Data3 d) { // 참조형 반환 타입 Data3
        Data3 tmp = new Data3(); // 새로운 객체 tmp를 생성
        tmp.x = d.x; // d.x의 값을 tmp.x에 복사
        return tmp; // 복사한 객체의 주소를 반환
    }
}

호출스택 예시

결과
d.x = 10
d2.x = 10


📌static 메서드와 인스턴스 메서드

인스턴스 메서드

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

static 메서드(클래스 메서드)

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

메서드 간의 호출과 참조

class TestClass2 {
	int iv;        // 인스턴스 변수
    static int cv; // 클래스 변수
    
    void instanceMethod() {     // 인스턴스 메서드
    	System.out.println(iv); // 인스턴스 변수 사용 가능
        System.out.println(cv); // 클래스 변수는 언제든지 사용 가능
    }
    
    static void instanceMethod() { // static 메서드
    	System.out.println(iv);    // 에러! 인스턴스 변수 사용 불가
        System.out.println(cv);    // 클래스 변수는 언제든지 사용 가능
    }
  • static 메서드는 객체 생성 없이 호출 가능하지만 iv는 객체 생성 후 호출 가능하다. static 메서드가 호출되었을 때 객체가 생성됐을 수도 안됐을 수도 있기 때문에 iv를 사용할 수 없다.

Q&A

Q. static 메서드는 static 메서드 호출 가능?
A. 가능

Q. static 메서드는 인스턴스 변수(iv) 사용 가능?
A. 불가능

Q. static 메서드는 인스턴스 메서드 호출 가능?
A. 불가능

Q. 왜 static 메서드는 인스턴스 멤버(iv, im)를 쓸 수 없나요?
A. static 메서드 호출 시 객체(iv 묵음)가 없을 수도 있기 때문에


📌오버로딩(Overloading)

오버로딩(Overloading) : 한 클래스 안에 같은 이름의 메서드 여러 개를 정의하는 것

오버로딩이 성립하기 위한 조건 3가지
1. 메서드 이름이 같아야 한다.
2. 매개변수의 개수 또는 타입이 달라야 한다.
3. 반환 타입은 영향이 없다.

예시

int add(int a, int b) { return a+b; }
int add(int x, int y) { return x+y; }

오버로딩x, 중복정의

int add(int a, int b) { return a+b; }
long add(int a, int b) { return (long)(a+b); }

오버로딩x, 중복정의
반환 타입은 영향이 없기 때문에

long add(int a, long b) { return a+b; }
long add(long a, int b) { return a+b; }

오버로딩ok

  • 오버로딩 : 매개변수는 다르지만 같은 의미의 기능을 수행

📌생성자(Constructor)

생성자(Constructor) : 인스턴스가 생성될 때 마다 호출되는 "인스턴스 초기화 메서드"

  • 인스턴스 생성 시 수행할 작업(iv 초기화)에 사용
  • 이름이 클래스 이름과 같아야 한다.
  • 리턴 값이 없다.(void 안붙임)
  • 모든 클래스는 반드시 생성자(1개 이상)를 가져야 한다.

기본 생성자(default constructor)

매개변수가 없는 생성자

  • 생성자가 하나도 없을 때만, 컴파일러가 자동으로 추가해준다.
class Data_1 {
	int value;
}
class Data_2 {
	int value;
	Data_2(int x) { // 매개변수가 있는 생성자
    	value = x;
    }
}

class Ex6_11 {
	public static void main(String[] args) {
    	Data_1 d1 = new Data_1();
        Data_2 d2 = new Data_2(); // 컴파일 에러 발생
}        

Data_2 에는 이미 생성자가 있기 때문에 컴파일러가 자동으로 기본 생성자를 추가해주지 않아서 에러가 발생한다.
기본 생성자 Data_2() {} 를 추가해줘야 에러가 발생하지 않는다.

매개변수가 있는 생성자

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("white", "auto", 4);

실행 순서
1. Car c : 참조변수 c를 생성
2. new : 객체 생성
3. Car("white", "auto", 4) : 생성자를 호출해서 객체(iv 묶음) 초기화
4. = : 객체의 주소를 참조변수에 저장(연결)


📌생성자 this()

  • 생성자에서 다른 생성자를 호출할 때 사용
  • 다른 생성자 호출 시 첫 줄에서만 사용 가능
    - 쓰는 이유 : 코드의 중복을 제거하기 위해서
class Car {
	String color;
    String gearType;
    int door;
    
    Car() {
    	this("white", "auto", 4);
    }
    
    Car(String c, String g, int d) { 
    	color = c;
        gearType = g;
        door = d;
    }
}

📌참조변수 this

주의 : 생성자 this()와 아무련 연관이 없다.

  • 인스턴스 자신을 가리키는 참조변수
  • 인스턴스 메서드(생성자 포함)에서 사용 가능
  • 지역변수(lv)와 인스턴스 변수(iv)를 구별할 때 사용
Car(String color, String gearType, int door) { 
	this.color = color;
	this.gearType = gearType;
	this.door = door;
}
  • this.color는 iv, color는 lv

📌변수의 초기화

  • 지역변수(lv)는 반드시 수동 초기화 해야함

    호출스택은 재사용이 빈번한 메모리 공간이다. 메서드가 호출되고 사라질 때마다 지역변수를 자동 초기화 해주면 성능이 떨어지기 때문에 새로운 값을 다른 메서드에 덮어 씌운다. 따라서, 지역변수를 반드시 수동 초기화를 해줘야 한다.

  • 멤버변수(iv, cv)는 자동 초기화된다.

멤버변수(iv,cv)의 초기화

  1. 명시적 초기화(=)
  2. 초기화 블럭
    • 인스턴스 초기화 블럭(iv) : {} (거의 안씀)
    • 클래스 초기화 블럭(cv) : static {} -> cv 복잡한 초기화
  3. 생성자 -> iv 복잡한 초기화

멤버변수의 초기화 시점

  • 클래스 변수(cv) 초기화 시점 : 클래스가 처음 메모리에 올라갈 때 딱 한번
  • 인스턴스 변수(iv) 초기화 시점 : 인스턴스가 생성될 때 마다
class InitTest {
	static int cv = 1; // 명시적 초기화
    int iv = 1; // 명시적 초기화
    
    static { cv = 2; } // 클래스 초기화 블럭(복잡 초기화)
    {iv = 2; } // 인스턴스 초기화 블럭(복잡 초기화)
    
    InitTest() { iv = 3; } // 생성자(복잡 초기화)
} 


초기화 순서

  • cv -> iv
  • 자동 초기화 -> 간단 초기화(명시적 초기화) -> 복잡 초기화

0개의 댓글