[자바의 정석] 6장 객체지향 언어 1. 1~3 변수와 메서드
아래 내용은 자바의 정석 강의&책을 보면서 정리한 내용입니다.
들어가기 전에
자바 공부 방식
공부 방식은 아래와 같습니다.
- 객체지향 개념: 자바의 정석 6, 7장 보기 → 내가 이해한 개념을 A4용지에 2장으로 정리하여 암기하기!
- 공부 순서: 자바 기초&자바의 정석 ⇒ jsp, spring ⇒ 설계(디자인 패턴, 객체지향)
자바의 정석 6장 내용 리스트
이번 시간에는 아래 내용 중 객체지향언어 ~변수와 메서드 부분을 정리하겠습니다.
1. 객체 지향 언어
객체지향은 기존에 있는 프로그래밍 언어에 객체지향 개념만 추가된 것이다.
⭐ 객체지향언어: 프로그래밍 언어 + 객체지향 개념(규칙)[암기 필요]
OOP(객체 지향 프로그래밍) 핵심 개념
- 캡슐화
- 상속
- 추상화
- ⭐️ 다형성: 가장 중요!
객체지향언어 특징
- 코드의 재사용성
- 코드의 관리 용이
- 신뢰성이 높은 프로그래밍 : 제어자와 메서드를 이용하여 데이터를 보호
2. 클래스와 객체
2.1 클래스와 객체의 정의와 용도
클래스 | 객체 | |
의미 | 객체를 정의해 놓은 것 → 객체를 생성하는데 사용 |
실제로 존재하는 것 → 객체가 가지고 있는 기능과 속성에 따라 다름 |
예시 | 제품 설계도 TV 설계도 |
제품 TV |
2.2 객체와 인스턴스
- 간단하게 같은 의미라고 생각하자.
객체 | 인스턴스 | |
의미 | 일반적으로 ‘객체’를 사용 | * 클래스 -(인스턴스화)→ 인스턴스(객체) * 어떤 클래스로부터 만들어진 객체를 강조할 때 사용 ex) TV 인스턴스 ⇒ TV 클래스로부터 만들어진 객체 |
2.3 객체의 구성요소 - 속성과 기능
⭐ 객체 = 속성(멤버변수) + 기능(메서드) 집합
아래와 같이 TV의 속성과 기능을 나눌 수 있고, 실제로 java에서 클래스 선언 시 변수와 메서드로 구성한다.
2.4 인스턴스 생성과 사용
객체를 생성하는 과정 두 가지를 살펴보자.
1) 객체 생성 과정
아래 객체 생성을 그림으로 한 줄씩 살펴보자.
// 1. 클래스 작성 (설계도)
class Tv {
// Tv 속성 (멤버 변수)
String color;
boolean power;
int channel;
// Tv의 기능(메서드)
void power(){ power =!power;}
void channelUp(){ ++channel;}
void channelDown() {--channel;}
}
public class TvTest {
public static void main(String[] args) {
// 2. 객체 생성
Tv t;
t = new Tv();
// 3. 객체 사용
t.channel = 7;
t.channelDown();
System.out.println("현재 채널은 " + t.channel + "입니다.");
}
}
-
- 메모리에 참조변수(리모컨) t 공간이 확보가 된다.
- 참조변수: 다른 변수의 메모리 위치를 저장하고 있는 변수를 의미한다. 참조변수 생성: Tv t;
- 메모리에 참조변수(리모컨) t 공간이 확보가 된다.
2. 객체 생성 & 참조변수에 넣기 : t = new Tv();
- 연산자 new에 의해 Tv클래스의 인스턴스가 메모리의 빈 공간에 생성
- 객체의 멤버들은 초기화되어 생성
- 대입 연산자를 통해 객체의 주소값이 t에 저장
3. 객체 사용: t.channel = 7;
- channel에 7을 저장한다.
4. 객체 사용: t.channelDown();
- channelDown 메서드를 호출하여 channel를 1 감소시킨다.
5. System.out.println("현재 채널은 " + t.channel + "입니다.");
- 감소된 6이 출력된다.
2) 객체 생성 과정 - 두 개
아래 예제에서 주의할 부분은 t2 = t1;이다. t2가 지닌 참조변수가 변경되는 부분이다.
class Tv {
// Tv 속성 (멤버 변수)
String color;
boolean power;
int channel;
// Tv의 기능(메서드)
void power(){ power =!power;}
void channelUp(){ ++channel;}
void channelDown() {--channel;}
}
public class TvTest {
public static void main(String[] args) {
Tv t1 = new Tv();
Tv t2 = new Tv();
System.out.println("t1 현재 채널은 " + t1.channel + "입니다.");
System.out.println("t2 현재 채널은 " + t2.channel + "입니다.");
t2 = t1;
t1.channel = 7;
System.out.println("t1 현재 채널은 " + t1.channel + "입니다."); // t1 현재 채널은 7입니다.
System.out.println("t2 현재 채널은 " + t2.channel + "입니다."); // t2 현재 채널은 7입니다.
}
}
- Tv t1 = new Tv(); Tv t2 = new Tv();
2. t2 = t1;
- t2도 t1과 동일한 값을 참조한다.
- 결과적으로 0x200번지 객체는 참조하지 않아 GC에 의해 제거된다.
2.5 객체 배열
⭐ 객체 배열 == 참조변수 배열
아래는 3개의 Tv 객체를 만드는 방법입니다.
class Tv {
// Tv 속성 (멤버 변수)
String color;
boolean power;
int channel;
// Tv의 기능(메서드)
void power(){ power =!power;}
void channelUp(){ ++channel;}
void channelDown() {--channel;}
}
public class TvTest {
public static void main(String[] args) {
Tv[] tvArr = new Tv[3];
for(int i = 0; i < tvArr.length; i++){
tvArr[i] = new Tv();
}
}
}
- Tv [] tvArr = new Tv[3];
- new Tv[3]는 참조변수 배열을 의미한다.
2. for(int i = 0; i < tvArr.length; i++){ tvArr[i] = new Tv(); }
- for문을 돌려 Tv라는 객체를 생성해준다.
2.6 클래스의 또 다른 정의
클래스는 크게 3가지 의미를 지닌다.
- 설계도
- 객체를 생성하기 위한 틀
- 데이터 + 함수 (구조체 + 함수)
- 클래스는 데이터와 함수의 결합으로 즉, 구조체 + 함수이다.
- 사용자 정의 타입
- 사용자가 원하는 타입을 직접 만들 수 있다.
3. 변수와 메서드
3.1 선언위치에 따른 변수의 종류
변수는 클래스 변수, 인스턴스 변수, 지역 변수 모두 세 종류가 있다. 자세한 부분은 표를 보면 알 수 있다.
변수의 종류 | 선언 위치 | 생성 시기 | 설명 |
클래스 변수 (CV) | 클래스 영역 | 클래스가 메모리에 올라갈 때 | - 클래스 변수 선언 방법은 앞에 static를 붙이면 됨 - 인스턴스마다 독립적인 저장공간을 갖는 인스턴스 변수와 다르게 클래스 변수는 모든 인스턴스가 공유하게 된다. - 객체 생성이 필요없이 사용 가능 - 접근하기 위해 “클래스이름.클래스변수” - public을 넣으면 프로그램 내 어디서나 접근할 수 있는 전역변수 성격을 지님 |
인스턴스 변수 (IV) | 클래스 영역 | 인스턴스 생성 시 | - 값을 읽거나 저장을 위해서는 인스턴스를 생성해야함 - 인스턴스는 독립적인 저장공간을 가진다. |
지역 변수 (LV) | 클래스 영역 이외의 영역 (메서드, 생성자, 초기화 블럭 내부) |
변수 선언문이 수행되었을 때 | - 메서드 내에서만 사용 가능하며 메서드 종료되면 소멸되어 사용이 불가능하다. - {} 블록 내에서만 사용 가능 |
3.2 클래스변수와 인스턴스변수
⭐ 클래스 변수:
아래 예시와 같이 모든 카드가 공통으로 가진 속성을 선언한다. ex) 카드의 폭, 높이
⭐ 인스턴스 변수:
개별 속성인 경우 사용 ex) 카드의 무늬, 숫자
- c1.width = 50;
- 클래스 변수를 변경하면 인스턴스가 하나의 저장공간을 공유하여 모두 변경된 값을 지닌다.
class Card {
String kind;
int number;
// 클래스 변수: 모든 객체가 동일한 경우 사용
static int width = 100;
static int height = 200;
}
public class CardTest {
public static void main(String[] args) {
System.out.println(Card.width + " " + Card.height); // 100 200
Card c1 = new Card();
c1.kind = "Heart";
c1.number = 7;
Card c2 = new Card();
c1.kind = "Space";
c1.number = 4;
c1.width = 50;
System.out.println(c1.width); // 50
System.out.println(c2.width); // 50
System.out.println(Card.width);// 50
}
}
- 메모리 구조로 그려보기!
- jvm 메모리 구조 개념은 아래 3.7에서 자세히 나온다.
- 여기서 중요하게 파악할 부분은 클래스 변수는 공유된다는 점이다.
3.3 메서드
메서드는 크게 선언부와 구현부로 이루어져 있다.
선언부
- 메서드 이름
- 반환 타입
- 반환 값을 적어준다.
- 반환값이 없는 경우 ‘void’ 적어야 한다.
구현부
- return문
- void가 아닌 경우 return 반환값이 반시드 존재
- 반환타입과 일치하거나 자동 형변환이 가능한 것만 가능
3.7 JVM 메모리 구조
응용프로그램이 실행되면 JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고, JVM은 이 메모리를 용도에 따라 여러 영역으로 나눠 관리한다. 그중 주요 영역인 메서드, 스택, 힙 영역에 대해 알아보자. 주요 영역은 스택을 제외한 나머지 영역은 스레드 간 공유를 한다.
1) 메서드 영역
- 클래스파일(*. class)을 읽어 분석하여 이곳에 저장한다. 이곳에는 클래스, 인터페이스 static 영역 등을 저장한다.
- 스레드 간 공유
2) 스택 영역
- 메서드의 작업에 필요한 메모리 공간을 제공한다.
- 메서드가 호출되면 호출스택에 호출된 메서드를 위한 메모리가 할당된다.
- 메서드가 완료되면 할당된 메모리공간은 반환되어 비워진다.
- 쓰레드간 해당 공간을 공유하지 않는다.
- 지역 변수, 리턴값 등 임시 값 생성
3) 힙 영역
- 인스턴스가 생성되는 공간
- 쓰레드간 공유
- new 키워드로 생성되는 객체, 배열로 gc가 주기적으로 제거하는 영역
3.8 기본형 매개변수와 참조형 매개변수
⭐ 기본형 매개변수: 변수의 값을 읽기만 가능 (read) → 값 전달
⭐ 참조형 매개변수: 변수의 값을 읽고 변경 가능 (read & write) → 주소를 전달
아래는 기본형, 참조형 매개변수 예제이다.
class Data {int x;}
public class PrimitiveEx {
static void primitiveChange(int x){
x = 100;
System.out.println("primitiveChange x:" + x); // primitiveChange x:100
}
static void ReferChange(Data d){
d.x = 1000;
System.out.println("ReferChange x: " + d.x); // ReferChange x: 1000
}
public static void main(String[] args) {
Data d = new Data();
d.x = 10;
System.out.println("main x:" + d.x); // main x:10
// 1. 기본형 매개변수: 변경 안됨
primitiveChange(d.x);
System.out.println("main x:" + d.x); // main x:10
// 2. 참조형 매개변수: 변경됨
ReferChange(d);
System.out.println("main x:" + d.x); // main x:1000
}
}
1) 기본형 매개변수 과정
- ReferChange 메서드 호출되면서, d.x가 ReferChange 메서드의 매개변수 x로 복사됨
- 값 자체를 copy
2. ReferChange 메서드에서 x 값을 1000 변경
- 지역 변수 값 1000 변경
3. ReferChange 메서드가 종료되면서 매개변수 x는 스택에서 제거
2) 참조형 매개변수 과정
- ReferChange 메서드가 호출되면서 참조변수 d의 값(주소)이 매개변수 d에 복사됨
- 주소값을 복사
2. ReferChange 메서드에서 매개변수 d로 x 값 1000 변경
3. ReferChange 메서드 종료되면서 매개변수 d는 스택에서 제거됨
3.11 클래스 메서드(static 메서드)와 인스턴스 메서드
⭐ 클래스 메서드(static 메서드): 인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드 사용하지 않는) 메서드를 정의
⭐ 인스턴스 메서드: 인스턴스 변수와 관련된 작업을 하는. 즉, 메서드 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드
⇒ 인스턴스 변수(iv)를 사용하는지 여부에 따라 구분됨
클래스 메서드(static 메서드) 인스턴스 메서드
클래스 메서드(static 메서드) | 인스턴스 메서드 | |
정의 | 인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드 사용하지 않는) 메서드를 정의 ex) Math.random() |
인스턴스 변수와 관련된 작업을 하는. 즉, 메서드 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드 |
언제 사용 | - 인스턴스 변수(iv) & 인스턴스 메소드를 사용하지 않는 경우 | 인스턴스 변수를 사용하는 경우 |
특징 | - 인스턴스 변수 사용 불가 - 인스턴스 메소드 사용 불가 |
|
호출 방식 | 클래스이름.메서드이름() | 참조변수.메서드이름() |
두 클래스 사용 방법은 아래 예시와 같다.
class MyMath2 {
long a, b;
// 인스턴스 메소드 - 인스턴스 변수를 사용
long add(){return a + b;}
long subtract(){return a - b;}
long multiply(){return a * b;}
long divide(){return a / b;}
// 클래스 메소드(static 메서드) - 인스턴스 변수를 사용 안함!
static long add(long a, long b){return a + b;}
static long subtract(long a, long b){return a - b;}
static long multiply(long a, long b){return a * b;}
static long divide(long a, long b){return a / b;}
}
public class MyMathTest2 {
public static void main(String[] args) {
// 1. 클래스 메소드 호출 - 객체 생성 필요 없음
System.out.println(MyMath2.add(200L, 100L));
System.out.println(MyMath2.subtract(200L, 100L));
System.out.println(MyMath2.multiply(200L, 100L));
System.out.println(MyMath2.divide(200L, 100L));
// 2. 인스턴스 메소드 호출 - 객체 생성 필요
MyMath2 mm = new MyMath2();
mm.a = 200L;
mm.b = 100L;
System.out.println(mm.add());
System.out.println(mm.subtract());
System.out.println(mm.multiply());
System.out.println(mm.divide());
}
}
3.12 클래스 멤버와 인스턴스 멤버 간의 참조와 호출
아래 예시와 같이 클래스 메서드는 인스턴스 메소드 or 변수를 호출할 수 없다.
- 이유? 클래스 메서드가 존재하는 시점에 인스턴스 멤버가 존재하지 않을 수 있다.
- 객체를 생성하지 않으면 인스턴스 멤버는 없다.
class Test {
int iv;
static int cv;
// 인스턴스 메소드
void instanceMethod2(){
}
void instanceMethod(){
}
// 클래스 메소드
static void classMethod2(){
}
static void classMethod(){
classMethod2();
instanceMethod2(); // 인스턴스 메소드 호출 불가
System.out.println(cv);
System.out.println(iv); // 인스턴스 변수 호출 불가
}
}
다음 시간에는 자바의 정석 6장 객체지향 언어 1 - 오버로딩, 생성자, 변수의 초기화에 대해서 알아 보겠습니다. 😀