솜이의 데브로그

Chapter 06 ) 객체지향프로그래밍(1) 본문

책을 읽자/Java의 정석

Chapter 06 ) 객체지향프로그래밍(1)

somsoming 2021. 9. 4. 14:49

참고 : Java의 정석

 

1. 객체지향언어

 

객체지향 이론은 상속, 캡슐화, 추상화 개념을 중심으로 발전되었다.

객체지향 언어의 가장 큰 장점은 '코드의 재사용성이 높고 유지보수가 용이하다.' 는 것이다. + 중복제거

 

<특징>

  1. 코드의 재사용성이 높다.
  2. 코드의 관리가 용이하다.
  3. 신뢰성이 높은 프로그래밍을 가능하게 한다. (코드의 중복을 제거하여 코드의 불일치로 인한 오동작 방지)

 

2. 클래스와 객체

클래스

클래스란 객체를 정의해놓은 것으로, 객체를 생성하는데 사용한다.

JDK에서는 많은 클래스 (Java API)를 제공하고 있다.

 

인스턴스

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

 

★ 내가 계속 궁금했던 부분

인스턴스와 객체는 같은 의미지만, 객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖고 있으며, 인스턴스는 어떤 클래스로부터 만들어진 것인지를 강조하는 보다 구체적인 의미를 갖고 있다.

 

객체의 구성요소

  • 속성(property) : 멤버변수, 특성, 필드, 상태
  • 기능(function) : 메서드, 함수, 행위

 

인스턴스의 생성과 사용

클래스명 변수명;
변수명 = new 클래스명();


Tv t;
t = new Tv();


Tv t = new Tv();

일반적으로 위와 같다.

인스턴스는 참조변수를 통해서만 다룰 수 있으며, 참조변수의 타입은 인스턴스의 타입과 일치해야한다.

+ 인스턴스를 생성했을 때, 멤버 변수는 각 자료형에 해당하는 기본값으로 초기화된다.

 

참조변수에는 하나의 값(주소)만이 저장될 수 있으므로 둘 이상의 참조변수가 하나의 인스턴스를 가리키는 것은 가능하지만 하나의 참조변수로 여러 개의 인스턴스를 가리키는 것은 불가능하다.

 

객체 배열

String 배열처럼, 객체 배열 안에 객체의 주소를 저장하는 배열.ex)

Tv[] tvArr = new Tv[3];

 

위의 예시에서 각 요소는 참조변수의 기본값인 null로 자동초기화된다.이 빈칸에 각 객체를 생성해야한다.

 

Tv[] tvArr = new Tv[3];

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

이렇게! 또는 배열의 초기화 블럭을 사용해 다음과 같이 한줄로 사용 가능하다.

Tv[] tvArr = { new Tv(), new Tv(), new Tv() };

 

for문으로도 초기화 가능하다.

 

 

3. 변수와 메서드

 

변수는 클래스변수, 인스턴스변수, 지역변수 세가지가 있다.  이를 결정하는 것은 '변수의 선언된 위치' 이다.

멤버변수를 제외한 나머지는 모두 지역변수이며, 멤버 변수 중 static이 붙은 것은 클래스변수, 붙지 않은 것은 인스턴스변수이다.

 

(클래스 영역에 선언되어 있어야 멤버변수)

ex)

class Variables
{
	int iv;  //인스턴스 변수
    static int cv;  //클래스 변수
    
    void method(){
    	int lv = 0;  //지역변수
    }
}

 

 

(1) 인스턴스 변수 

클래스 영역에 선언되며, 클래스의 인스턴스를 생성할 때 만들어진다. 인스턴스마다 독립적으로 서로 다른 값을 가진다.

 

(2) 클래스변수

모든 인스턴스가 공통된 저장공간을 공유한다. 인스턴스변수와 달리 인스턴스를 생성하지 않고도 언제라도 바로 사용할 수 있다. '클래스이름.클래스변수' 형식으로 사용.

클래스가 메모리에 로딩(loading) 될 때 생성되어 프로그램 종료시까지 유지되며, public을 붙이면 전역변수의 성격을 갖는다.

 

(3) 지역변수

메서드 내에 선언되어 메서드가 종료되면 소멸된다. (클래스 이외의 메서드, 생성자, 초기화블럭 등에서 선언)

 

→ 정리하자면, 인스턴스변수는 인스턴스가 생성될 때마다 생성되므로 인스턴스마다 다른 값을 가지지만, 클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유(참조)하므로 항상 공통된 값을 갖는다.

 

메서드

메서드(method)는 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것이다.

 

메서드의 장점

  1. 높은 재사용성 (reusability)
  2. 중복 코드의 제거
  3. 프로그램의 구조화. 프로그램의 전체 흐름을 한 눈에 확인할 수 있도록 단순하게 구조화하는 것이 좋다.

 

※ 같은 클래스 내의 메서드끼리는 참조변수 없이 서로 호출이 가능하지만, static 메서드는 같은 클래스 내의 인스턴스 메서드를 호출 할 수 없다. (생각해보면 당연한듯)

 

 

JVM의 메모리 구조

(1) 메서드 (method area)

프로그램 실행 중 어떤 클래스가 사용되면 해당 클래스의 클래스파일을 읽어 정보를 이곳에 저장한다. 이 때 그 클래스의 클래스변수도 함께 생성된다.

 

(2) 호출스택 (call stack / execution stack)

메서드의 작업에 필요한 메모리 공간을 제공한다. 메서드가 호출되면 호출된 메서드를 위한 메모리가 할당되며, 이 메모리는 메서드가 작업을 수행하는 동안 지역변수들과 연산의 중간결과 등을 저장하는데 사용한다.메서드 작업이 끝나면 메모리 공간은 반환되어 비어짐. (일반적인 스택 떠올리기!)

 

(3) 힙

인스턴스가 생성되는 공간. 프로그램 실행 중 생성되는 모두 이곳에 생성된다. 인스턴스 변수들이 생성되는 공간.

 

 

반환타입이 '참조형'이라는 것은 메서드가 '객체의 주소'를 반환한다는 것을 의미한다.

또한 메서드 작성에 있어서 매개변수의 유효성을 반드시 검사해야한다! 이는 시큐어코딩을 위한 방법이기도 하다.

 

 

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

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

클래스메서드 역시 객체를 생성하지 않고도 클래스이름.메서드이름(매개변수) 로 호출 가능하다.

 

인스턴스 메서드는 인스턴스 변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드이다. 반면 인스턴스와 관계없는 메서드를 클래스 메서드라고 한다.

  1. 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙인다.
  2. 클래스 변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
  3. 클래스 메서드는 인스턴스 변수를 사용할 수 없다.
  4. 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.

 

클래스 멤버가 인스턴스 멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야한다.

 

 

4. 오버로딩

한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것을 '메서드 오버로딩' 이라 한다.

 

오버로딩의 조건

  1. 매서드 이름이 같아야 한다.
  2. 매개변수의 개수 또는 타입이 달라야 한다.

반환 타입은 오버로딩을 구현하는데 아무런 영향을 주지 못한다.

 

가변인자

'타입... 변수명' 과 같은 형식으로 선언한다.  ex)  Object... args

따라서 매개변수의 개수를 동적으로 지정 할 수 있다. 또한 가변인자는 매개변수 중에서 제일 마지막에 선언해야한다. 그렇지 않으면 컴파일 에러가 발생한다.

가변인자를 사용하면 내부적으로 배열을 이용한다. (길이가 0인 배열도 가능)

가능하면 가변인자를 사용한 메서드는 오버로딩 하지 않는 것이 좋다.

 

 

5. 생성자 (Constructor)

생성자는 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'이다.

 

생성자의 조건

  1. 생성자의 이름은 클래스의 이름과 같아야 한다.
  2. 생성자는 리턴값이 없다.

생성자도 오버로딩이 가능하다. 컴파일 시, 소스파일의 클래스에 생성자가 하나도 정의되어있지 않은 경우 컴파일러가 자동적으로 기본 생성자를 추가하여 컴파일한다.

그러나 기본생성자가 컴파일러에 의해서 추가되는 경우는 클래스에 정의된 생성자가 하나도 없을때 뿐이므로, 생성자를 오버로딩하고자하면 기본 생성자를 반드시 적어줘야한다.

 

생성자 간 서로 호출 시

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

 

ex) 

class Car {
	String color;
    String gearType;
    int door;
    
    Car(){
    	this("white", "auto", 4);
    }
    Car(String color, String gearType, int door){
    	this.color = color;
        this.gearType = gearType;
        this.door = door;
    }
}

 

this는 참조변수로 인스턴스 자신을 가리킨다. this를 통해 인스턴스 변수에 접근할 수 있다.

 

→ 인스턴스를 생성할 때는 다음의 2가지 사항을 결정해야한다.

  1. 클래스 - 어떤 클래스의 인스턴스를 생성할 것인가?
  2. 생성자 - 선택한 클래스의 어떤 생성자로 인스턴스를 생성할 것인가?

 

6. 변수의 초기화

멤버변수는 초기화를 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지지만, 지역변수는 사용하기 전에 반드시 초기화해야 한다.

 

가능하면 선언과 동시에 적절한 값으로 초기화를 하는 것이 바람직하다.

 

멤버변수의 초기화 방법

  • 명시적 초기화
  • 생성자
  • 초기화 블럭 - 인스턴스 초기화 블럭, 클래스 초기화 블럭

 

초기화 블럭은 단순히 클래스 내에 블럭{}를 만들고 그 안에 코드를 작성하면 된다. 클래스 초기화 블럭 역시 인스턴스 초기화 블럭 앞에 static 붙이면 된다.

 

클래스 초기화 블럭은 클래스가 메모리에 처음 로딩될 때 한번만 수행되며, 인스턴스 초기화 블럭은 생성자와 같이 인스턴스를 생성할 때 마다 수행된다. 또한 생성자보다 인스턴스 초기화 블럭이 먼저 수행됨을 기억하자!

 

클래스 변수의 초기화 순서 : 기본값 → 명시적초기화 → 클래스초기화 블럭인스턴스변수의 초기화 순서 : 기본값 → 명시적초기화 → 인스턴스초기화 블럭 → 생성자

 

 

 

확실히 자바 세번째 분석하면서 공부하니까 훨씬 객체지향 개념 이해가 수월하다. 그냥 아는거 복습이라 지금은 할만한데 처음 배울때 진짜 뭔소린지 얼마나 이해하기 어려웠는지ㅋㅋㅋ 처음 배우는 나를 이해시킨 도교수님 정말 대단하시다..

'책을 읽자 > Java의 정석' 카테고리의 다른 글

Chapter 08 ) 예외처리  (0) 2021.09.10
Chapter 07 ) 객체지향프로그래밍(2)  (0) 2021.09.08
Chapter 05 ) 배열 array  (0) 2021.09.03
Chapter 04 ) 조건문과 반복문  (0) 2021.09.03
Chapter 03 ) 연산자 operator  (0) 2021.09.03