Cute Running Puppy

Language/[Java] 자바의 정석

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

R.silver 2023. 2. 10. 14:13
반응형

객체지향언어

객체지향언어의 역사

기본 이론

실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물간의 상호작용이다

객체지향언어

주요 특징

  1. 코드의 재사용성이 높다
  2. 새로운 코드를 작성할 때 기존의 코들를 이용하여 쉽게 작성할 수 있다
  3. 코드의 관리가 용이하다
  4. 코드간의 관계를 이용해서 적은 노력으로 쉽게 코드를 변경할 수 있다
  5. 신뢰성이 높은 프로그래밍을 가능하게 한다
  6. 제어자와 메서드를 이용해서 데이터를 보호하고 올바른 값을 유지하도록 하며, 코드의 중복을 제거하여 코드의 불일치로 인한 오동작을 방지할 수 있다

코드의 재사용성이 높고 유지보수가 용이하다라는 특징은 프로그램 개발, 유지보수에 드는 시간과 비용을 획기적으로 개선하였다

재사용성, 유지보수, 중복 코드 제거라는 3가지 관점에서 객체 지향 개념을 이해한다면 보다 쉽게 접근 가능

클래스와 객체

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

클래스는 객체의 설계도, 틀

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

클래스정의

객체를 정의해 놓은 것

클래스 용도

객체를 생성하는 데 사용

프로그래밍에서 객체

클래스에 정의된 내용대로 메모리에 생성된 것

객체의 정의

실제로 존재하는 것, 사물 혹은 개념

객체의 용도

객체가 가지고 있는 기능과 속성에 따라 다름

유,무형의 객체가 있음

클래스는 객체를 생성되는 데 사용하는 것일 분 객체 자체는 아니다

tv 설계서가 tv가 아닌 것과 같이

객체를 사용하기 위해서는 클래스로부터 객체를 생성하는 과정이 선행되어야 한다

이러한 특성으로 클래스를 한 번만 잘 만들어 둔다면 객체를 생성할 때마다 고민하지 않아도 된다

그냥 사용하면 된다

JDK는 유용한 클래스를 기본적으로 제공한다

객체와 인스턴스

클래스로 객체 만들기== 인스턴스화 (instantiate)

클래스로 만든 객체 == 인스턴스 (instance)

인스턴스와 객체는 동일한 의미이지만,

객체는 모든 인스턴스를 대표하는 포괄적 의미, 인스턴스는 어떤 클래스로부터 만들어 진 것인지를 강조하는 보다 구체적인 의미

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

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

객체 == 속성과 기능의 집합 == 객체의 멤버 (member)

클래스 == 객체를 정의한 것 ⇒ 클래스에는 객체의 모든 속성과 기능의 정의 되어 있음

속성 → 멤버 변수

기능 → 메서드

인스턴스의 생성과 사용

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

Tv t;
t = new Tv();

참조 변수를 생성만 하고 인스턴스를 생성하지 않고 연결하지 않으면, 해당 참조 변수로 아무 것도 할 수 없다

new() 코드를 작성해주어야 클래스의 인스턴스가 메모리의 빈 공간에 생성된다

= 대입 연산자로 생성된 객체의 주소 값을 참조변수에 저장해야 한다

  1. 참조 변수 선언
  2. 객체 생성
  3. 객체의 주소를 참조 변수에 저장

인스턴스는 오직 참조변수를 통해서만 다룰 수 있으며

참조변수의 타입은 인스턴스의 타입과 일치해야 한다

같은 클래스로부터 생성되었더라고 각 인스턴스의 속성(멤버변수)는 서로 다른 값을 유지할 수 있다

...
Tv t1 = new Tv();
Tv t2 = new Tv();

t2 = t1; // t1, t2는 동일한 인스턴스를 가리킴
// t2가 가리키던 인스턴스는 더 이상 사용할 수 없다 
...

참조변수에는 하나의 값(주소)만이 저장될 수 있다

둘 이상의 참조변수가 하나의 인스턴스를 참조하는 것은 가능하지만

하나의 참조변수가 여러 개의 인스턴스를 가지는 것은 불가능하다

객체 배열

객체를 배열로 묶는 것

객체의 주소가 저장된다

즉, 객체 배열은 참조변수들을 하나로 묶은 참조 변수 배열

Tv t1, t2, t3;

Tv [] tvArr = new Tv[3]; // 객체 배열 - 아직 객체가 저장되지 않았음 

객체 배열의 각 요소는 참조변수의 기본값인 null로 자동 초기화

각 배열의 칸에 객체의 주소를 저장할 수 있다

가장 많이 받는 질문

객체 배열만 생성해 두고 객체를 생성햇는데 에러가 발생합니다!

⇒ 객체 배열을 생성하고 객체를 넣어야 한다

Tv [] tvArr = new tvArr[3]; // 객체 배열 생성 

// 객체를 각 요소에 저장 
// 방법 1 - 각 인덱스에 직접 접근 
tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();

// 방법 2 - 배열의 초기화 블럭 사용 
Tv[] tvArr = {new Tv(), new Tv(), new Tv()};

// 방법 3 - for 문 사용 
for (int i = 0 ; i < 3; i ++) 
	tvArr[i] = new Tv();

배열에는 한 종류의 객체만 저장할 수 있다.

여러 종류의 객체를 하나의 배열에 저장하기 위해서는…?

⇒ 다형성(polymorphism) 사용

클래스의 또 다른 정의

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

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

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

사용자 정의 타입: 프로그래머가 서로 관련된 변수를 묶어 하나의 타입으로 새로 추가하는 것

기본형의 개수가 8개로 정해져 있지만 참조형의 개수가 정해져 있지 않은 이유

// 비객체지향적 코드 
// 매번 시 분 초를 각각 정의해주어야 한다 
int hour1, hour2, hour3;
int minute1, minute2, minute3;
float second1, second2, second3;

int [] hour = new int[3];
int [] minute = new int [3];
float [] second = new float[3];
// 객체지향적 코드 
// 시 분 초를 하나의 클래스로 묶어 정의 
Time t1 = new Time();
Time t2 = new Time();
Time t3 = new Time();

Time [] t = new Time[3];
t[0] = new Time();
t[1] = new Time();
t[2] = new Time();

시, 분, 초 데이터를 하나로 묶는 것을 넘어서

해당 데이터의 제약 조건까지 모두 반영할 수 있다

(추가 제약 조건 - 시분초의 범위 제약)

객체지향 언어가 아닌 언어에서는 추가적인 조건까지 반영하기 쉽지 않다

객체지향 언어에서 제어자를 사용한다면 위와 같은 추가 제약 조건들을 설정할 수 있다

제어자를 통해 직접 멤버 변수에 값을 지정하는 것을 허용하지 않고, 메서드를 통해서만 값을 변경할 수 있도록 할 수 있다.

public class Time {
	private int hour;
	private int minute;
	private float second;

	public int getHour() {return hour;}
	public int getMinute() {return minute;}
	public float getSecond() {return second;}

	// 직접 값 변경하는 거 제어 & 유효성 검증 
	public void setHour(int h) {
		if (h < 0 || h > 23) return;
		hour = h;
	}

	public void getMinute(int m) {
		if (m < 0 || m > 59) return;
		minute= h;
	}

	public void getSecond(int s) {
		if (s < 0 || s > 23) return;
		second= s;
	}
}

변수와 메서드

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

변수의 종류

클래스 변수, 인스턴스 변수, 지역 변수

⇒ 변수가 선언된 위치가 변수의 종류를 결정한다

  1. 지역변수멤버 변수를 제외한 나머지 변수들은 모두 지역변수
  2. 메서드 영역에 선언된 변수
  3. 클래스 변수
  4. static이 붙은 멤버 변수
  5. 인스턴스 변수
  6. static 이 붙지 않은 변수
class Var
{
	int iv; // 인스턴스 변수 
	static int cv; // 클래스 변수 

	void method()
	{
		int lv = 0; // 지역 변수 
	}
}

변수의 종류 선언 위치 생성시기

calss variable class area 클래스가 메모리에 올라갈 때
instance variable class area 인스턴스가 생성되었을 때
local variable class area를 제외한 영역  
(메서드, 생성자, 초기화 블럭 내부) 변수 선언문이 수행되었을 때  

1. 인스턴스 변수

클래스 영역에 선언

클래스의 인스턴스를 생성할 때 생성

인스턴스 변수의 값을 불러오기 위해서는 인스턴스를 생성해야 한다

인스턴스마다 고유한 상태를 유지해야 한느 경우, 인스턴스 변수로 선언

2. 클래스 변수

인스턴스 변수 앞에 static 키워드 붙여 생성

모든 인스턴스가 공통된 저장공간(변수)을 공유하게 된다

한 인스턴스들이 공통적인 값을 유지해야 하는 속성일 때 사용

(클래스를 저장하는 변수라는 의미가 아님)

클래스 변수는 인스턴스를 생성하지 않고도 바로 사용할 수 있다

// 클래스 변수 사용 방법
클래스이름.클래스변수
Var.cv; // Var 클래스의 클래스 변수 cv 사용 

클래스가 메모리에 로딩될 때 생성되어 종료될 때 까지 유지

public을 붙이면 전역변수 성격을 갖는다

참조변수의 선언, 객체의 생성 등 클래스 정보가 필요할 때 메모리에 클래스가 로딩된다

3. 지역 변수

매서드 내에서만 사용 가능한 변수

메서드가 종료되면 소멸되어 사용불가

블럭을 벗어나면 소멸되어 사용할 수 없다

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

게임 카드를 클래스로 정의할 때

무늬 숫자는 인스턴스 변수로 정의,

카드의 크기는 클래스 변수로 정의하면 된다

(모든 카드들이 카드의 크기를 공유하기 때문)

인스턴스 변수는 인스턴스.변수명 으로 사용하고,

클래스 변수는 클래스명.변수명으로 사용한다 (클래스 변수를 인스턴스명.클래스변수명 으로도 사용할 수 있지만 혼동할 수 있기에 클래스명.변수명으로 사용하는 것이 바람직하다)

인스턴스 변수는 인스턴스가 생성될 때 마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유하므로, 항상 공통된 값을 갖는다.

메서드

특정 작업을 수행하는 일련의 문장들을 하나로 묶은것

입력값, 출력값 모두 없을 수도 있다

메서드가 내부적으로 어떤 과정을 거쳐 결과를 내는 지는 전혀 몰라도 된다.

오직 입, 출력 값만 알면 된다 (메서드를 블랙 박스라고 부르는 이유)

메서드를 사용하는 이유

  1. 높은 재사용성 (reusabiliy)다른 프로그램에서도 사용할 수 있다
  2. 한번 만들어 둔 메서드는 몇 번이고 호출 할 수 있으며,
  3. 중복된 코드의 제거소스코드의 길이도 짧아지고, 수정해야 할 코드의 양 또한 줄어들어 오류가 발생할 가능성도 줄어든다
  4. 반복되는 문장들을 하나의 메서드로 작성하여 중복된 코드를 제거할 수 있다
  5. 프로그램의 구조화main 메서드는 프로그램의 전체 흐름이 한 눈에 들어올 정도로 단순하게 구조화 하는 것이 중요하다
  6. 내용이 없는 메서드를 작업 단위로 만들어 놓고, 하나씩 완성해나가는 것도 좋은 방법
  7. 큰 규모의 프로그램에서는 문장들을 작업단위로 나눠서 여러 개의 메서드에 담아 프로그램의 구조를 단순화 시키는 것이 필수적이다

메서드의 선언과 구현

메서드 = 선언부 + 구현부

// 선언부 
반환타입 메서드이름 (타입변수명, 타입변수명, ...)
// 구현부 
{
		// 메서드 호출시 수행될 코드
}

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

메서드 선언부 (method declaration, method header)

메서드 선언부 = 메서드 이름 + 매개변수 선언 + 반환타입

메서드의 선언부는 후에 변경사항이 발생하지 않도록 신중히 작성

선언부가 변경되면 호출되는 모든 곳도 변경해야 하기 때문

매개변수 선언 (parameter declaration)

메서드가 작업을 수행하는 데 필요한 값들을 선언

필요한 값의 개수만큼 선언하여 쉼표로 구분

여러 변수의 타입이 같아도 변수의 타입을 생략할 수 없다

입력해야 할 값의 개수가 많은 경우 배열이나, 참조변수를 사용하면 된다

메서드의 이름 (method name)

명명규칙을 반영하여 메서드의 이름을 작성하면 된다

동사인 경우가 많으며

이름만으로 메서드의 기능을 알 수 있도록 함축적으로 작성하는 것이 좋다

반환 타입 (return type)

메서드의 작업 결과의 타입을 적는다

반환 값이 없으면 void를 적는다

메서드의 구현부(method body_

메서드 선언부 다음에 오는 괄호 == 메서드의 구현부

return 문

반환 타입이 void가 아닌 경우 구현부 안에 return 반환값;을 반드시 작성해야 한다

return 타입은 반환타입과 일치하거나 자동 형변환이 가능한 것이어야 한다

단 하나의 값만 반환할 수 있다

지역 변수 (local variable)

메서드 안에 선연된 변수

매개변수도 매서드 내에 선언된 것이므로 지역변수이다

다른 메서드에 선언되었다면 변수의 이름이 같더라도 다른 변수이다

메서드의 호출

메서드를 호출해야만 구현부의 문장들이 수행된다

main 메서드는 프로그램 실행 시 os에 의해 자동적으로 호출된다

// 메서드 호출 방법 
메서드이름 (값1, 값2, ...); 

int res = add(3, 5);

인자 (argument)와 매개변수 (parameter)

메서드를 호출할 때 지정해주는 값인 인자의 개수는

호출된 메서드에 선언된 매개변수의 수와 일치해야 한다.

메서드가 호출되면서 매개변수에 대입되므로, 인자의 타입은 매개변수의 타입과 일치하거나 자동형변환이 가능한 것이어야 한다

반환 타입이 void 가 아닌 경우 반환 값을 대입연산자로 변수에 저장하는 것이 보통이지만,

저장하지 않아도 괜찮다

메서드의 실행 흐름

같은 클래스 내의 메서드끼리는 참조변수를 사용하지 않고도 서로 호출이 가능하지만 static 메서드는 같은 클래스 내의 인스턴스 메서드를 호출 할 수 없다

클래스에 선언된 메서드를 호출하기 위해서는 클래스의 인스턴스를 생성한 뒤 참조변수를 통해 호출해야 한다

MyMath mm = new MyMath();
int res = mm.add(1,3); // 호출한 자리를 반환값이 대신하고 변수에 저장된다 
  1. main 메서드에서 add 메서드를 호출한다
  2. 호출시 지정한 인자들이 add의 매개변수 a, b에 복사 (대입)된다
  3. 메서드 add의 괄호 안에 있는 문장들이 순서대로 실행된다
  4. 메서드 add의 모든 문장이 실행되거나 , return 문을 만나면 호출한 메서드로 돌아와 이후의 문장들을 실행한다

메서드가 호출되면 지금까지 실행중이던 메서드는 실행을 잠시 멈추고, 해당 메서드의 작업이 마무리 되면 다시 실행된다

return 문

현재 실행중인 메서드를 종료하고 호출한 메서드로 되돌아간다

원래 반환값을 필수로 작성해주어야 하지만 컴파일러가 마지막에 return; 을 자동적으로 추가하기 때문에 필수로 작성하지 않아도 괜찮다

그러나 반환값이 void가 아닌 경우에는 반드시 return 문을 작성해야 한다

반환값(return value)

반환값으로 반드시 변수가 와야 하는 것은 아니다

수식이 와도 상관 없다

매개변수의 유효성 검사

메서드의 구현부를 작성할 대 가장 먼저 해야 하는 일은 매개변수의 값의 유효성을 검사하는 것이다

메서드를 작성할 때 호출하는 사람이 잘 넘기겠지 라는 생각을 절대로 가져서는 안된다

타입만 맞으면 어떠한 값이라도 넘어올 수 있기 때문에 가능한 모든 경우의 수에 대해 대비한 코드를 작성해야 한다

적절하지 않은 값이 매개변수를 통해 넘어온다면

매개변수의 값을 보정하던가, return을 사용하여 작업을 중단해야 한다

JVM의 메모리 구조

응용프로그램이 실행되면, JVM은 시스템으로부터 메모리를 할당받고, 용도에 따라 여러 영역으로 나누어 관리한다

1. 메서드 영억

프로그램 실행 중 어떤 클래스가 사용되면 JVM은 해당 클래스의 클래스 파일 (*.class)을 읽어 분석하여 클래스에 대한 정보 (class data)를 이곳에 저장한다

이 때, 그 클래스의 클래스 변수도 함께 저장된다

2. 힙(heap)

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

실행 중 생성되는 모든 인스턴스는 이곳에 생성된다

3. 호출스택(call stack 또는 execution stack)

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

메서드가 호출되면 호출된 메서드를 위한 메모리 할당

작업 중간중간 지역변수 (매개변수 포함) 들과 연산의 중간 결과 등을 저장하는 데 사용

작업을 마치면 할당된 메모리공간은 반환되어 비워짐

각 메서드를 위한 작업 공간은 서로 구분되며, stack 처럼 쌓인다

다음 메서드가 stack 영역에 들어오면 기존 메서드는 작업을 중단하고 새로 들어온 메서들를 작동시킨다.

호출스택에 가장 상위에 있는 메서드가 현재 실행중인 메서드이며, 나머지는 대기상태 메서드이다.

호출스택의 특징

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

반환타입이 있는 메서드는 종료되면서 결과값을 자신을 호출한 메서드(caller) 에게 반환한다

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

메서드를 호출할 때 매개변수로 지정한 값을 메서드의 매개변수에 복사하여 넘겨준다

매개변수 타입이

기본형이면 값이 복사되고

참조형이면 인스턴스 주소가 복사된다

참조형의 경우 인스턴스 주소가 복사되는 것이기에 변수의 값을 읽고 변경할 수 있다 (기본형은 읽기만 가능)

class Data {int x;}

... 
Data d = new Data();
d.x = 10;
change(d.x); // 200 - 복사된 값의 값이 변경됨 (원본은 변경 안됨)
System.out.println(d.x); // 10 - 그대로 

...

// 기본형 변수의 값을 변경
static void change(int x) {
	x = 200;
	System.out.println(x);
}
class Data {int x;}

... 
Data d = new Data();
d.x = 10;
change(d); // 200 - 객체 차제를 넘김
System.out.println(d.x); // 200 - 객체에 저장된 값이 변경됨 

...

// 매개변수를 참조형으로 선언 
// 참조형 변수의 값을 변경 
static void change(Data d) {
	d.x = 200;
	System.out.println(d.x);
}

참조형 매개변수를 활용하면 반환값이 없어도 메서드의 실행결과를 얻어올 수 있다

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

void add (int a, int b, int [] result) {
	result[0] = a + b;
}

참조형 반환타입

반환타입 또한 참조형이 될 수 있다

모든 참조형 타임의 값은 객체의 주소이므로 정수의 값이 반환되는 것 일 뿐이다

반환타입이 참조형이라는 것은

메서드가 객체의 주소를 반환한다는 것을 의미

class Data {int a;}

... main ...

Data d = new Data();
d.x = 10;

Data d2 = copy(d);

...

static Data copy(Data d) {
	Data tmp = new Data();
	tmp.x = d.x;

	return tmpl
	}
}

재귀 호출 (recursive call)

메서드의 내부에서 메서드 자신을 호출하는 것

메서드 입장에선느 자기 자신을 호출하는 것이나 다른 메서드를 호출하는 것이나 동일하다

호출된 메서드는 call by value를 통해 원래의 값이 아닌 복사된 값으로 작업, 호출된 메서드와 관계없이 독립적인 작업이 가능

재귀 호출에서 종료 조건이 없다면 무한히 반복되기 때문에 종료조건을 잊지 않고 작성해야 한다 재귀 호출은 반복문과 유사하기에 대부분의 재귀호출은 반복문으로 작성하는 것이 가능하다

(그렇다면 반복문을 재귀로 변경하는 것도 가능하다는 소리!)

반복문보다 재귀호출의 수행시간이 더 오래걸린다 (매개변수 복사, 종류 후 복귀할 주소 저장 등등 필요)

재귀호출을 사용하는 이유

논리적 간결함

재귀 호출은 비효율적이므로 재귀호출에 드는 비용보다 재귀호출의 간결함이 주는 이득이 충분히 큰 경우에만 사용해야 한다

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

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

staic 키워드 사용 static 키워드 미사용

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

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

인스턴스 변수는 인스턴스를 생성해야만 만들어지므로

인스턴스 메서드 역시 인스턴스를 생성해야만 호출할 수 있다

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

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

  1. 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙인다
  2. 클래스 변수 (static 변수)는 인스턴스를 생성하지 않아도 사용할 수 있다
  3. 클래스가 메모리에 올라갈 때 이미 자동적으로 생성
  4. 클래스 메서드 (static 메서드)는 인스턴스 변수를 사용할 수 없다클래스 메서드는 인스턴스가 없어도 사용 가능하기에 인스턴스 변수가 존재하지 않을 수도 있다하지만 인스턴스 변수나 인스턴스메서드에서 static이 붙은 멤버를 사용하는 것은 가능하다
  5. 그래서 클래스 메서드에 인스턴스 메서드 사용을 금지하는 것이다
  6. 인스턴스 변수는 인스턴스가 반드시 존재해야 한다
  7. 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다static 을 붙이지 않은 인스턴스 메서드는 실행 시 호출되어야 할 메서드를 찾는 과정이 필요하기에 시간이 더 걸린다
    • 클래스 멤버변수 중 모든 인스턴스에 공통된 값을 유지해야 하는 것이 있는지 살펴보고 있으면 staitc
    • 작성한 메서드 중 인스턴스 변수나 인스턴스 메서드를 사용하지 않는 메서드의 static을 붙을 것을 고려한다
  8. 메서드 호출 시간이 짧아지므로 성능이 향상된다

+) Math 클래스의 메서드는 모두 클래스 메서드 (인스턴스 변수 없고, 수행하는데 필요한 모든 값들을 매개변수로 받아 처리)

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

클래스 멤버가 인스턴스 멤버를 참조, 호출하기 위해서는 인스턴스를 생성해야 한다

∵ 인스턴스 멤버가 존재하는 시점에 클래스 멤버는 항상 존재하짐나, 클래스 멤버가 존재하는 시점에 인스턴스 멤버가 존재하지 않을 수도 있기에

// 아래와 같이 축약 가능 
int result = new MemberCall().instanceMethod1();

// 이 경우 참조변수를 사용하지 않았기 땜누에 생성된 MemberCall 인스턴스는 더 이상 사용 불가 
반응형