객체지향언어
객체지향 언어의 주요 특징
- 코드의 재사용성이 높다. → 기존의 코드 재사용
- 코드의 관리가 용이하다. → 적은 노력으로 쉽게 코드 변경 가능
- 신뢰성이 높은 프로그래밍을 가능하게 한다. → 제어자와 메서드를 이용해서 데이터를 보호하고 올바른 값을 유지하도록 한다.
너무 객체지향개념에 얽매여서 고민하기보다는 일단 프로그램을 기능적으로 완성한 다음 어떻게 하면 보다 객체지향적으로 코드를 개선할 수 있을지를 고민하여 점차 개선해 나가는 것이 좋다.
우아한 프리코스 1주차 미션인 숫자야구게임을 풀 때... 시작부터 객체지향적으로 짜고 싶어 헤맸던 기억이 떠올랐다..
앞으로 기능을 먼저 구현한 후 개선해야겠다.
클래스와 객체
- 클래스 : 객체를 정의해놓은 것
- 객체 : 객체의 설계도 또는 틀
객체의 구성 요소 - 속성과 기능
객체는 속성과 기능의 집합 !
- 속성 : 멤버 변수, 특성, 필드, 상태
- 기능 : 메서드, 함수, 행위
실제로 예를 들면
TV의 속성 : 크기, 길이, 높이, 색상, 볼륨, 채널 등
TV의 기능 : 켜기, 끄기, 볼륨 높이기, 볼륨 낮추기, 채널 변경하기 등
코드로 예를 들면
class Tv {
// 속성
String color;
boolean power;
int channel
// 기능
void power()
void channelUp()
void channelDown()
}
인스턴스 대입
Tv t1 = new Tv();
Tv t2 = new Tv();
t2 = t1
위처럼 코드를 작성할 경우 t1이 저장하고 있는 값(t1이 가리키는 객체 주소)을 t2에 저장한다.
t1은 참조변수이므로, 인스턴스의 주소를 저장하고 있다. 세 번째 문장이 수행되면, t2가 가지고 있던 주소를 잃어버리게 되고 t1에 저장되어 있던 주소가 t2가 저장된다. 그렇게 되면 t2가 원래 참조하고 있던 인스턴스는 더 이상 사용할 수 없게 되며 이후 가비지 컬렉터에 의해 자동적으로 메모리에서 제거된다.
객체 배열
Tv[] tvArr = new Tv[3];
tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();
위 코드를 보면 알 수 있듯이, 객체 배열을 생성하는 것은 그저 객체를 다루기 위한 참조 변수들이 만들어진 것일 뿐, 아직 객체가 생성되지는 않았다. 객체를 생성해서 객체배열 요소에 저장하는 것을 잊으면 안 된다!!
// 비객체지향적인 코드
int hour1, hour2, hour3;
int minute1, minute2, minute3;
float second1, second2, second3;
// 객체지향적인 코드
class Time {
int hour;
int minute;
float second;
}
Timte t1 = new Time();
Timte t2 = new Time();
Timte t3 = new Time();
변수와 메서드
선언 위치에 따른 변수의 종류
- 인스턴스마다 독립적인 저장공간을 갖는 인스턴스 변수와 달리, 클래스 변수는 모든 인스턴스가 공통된 저장공간(변수)을 공유하게 된다.
메서드를 사용하는 이유
- 높은 재사용성
- 중복된 코드의 제거
- 프로그램의 구조화
- 문장들을 작업 단위로 나눠서 여러 개의 메서드에 담아 프로그램의 구조를 단순화시킨다.
++ 객체를 생성하지 않고도 메서드를 호출할 수 있으려면 메서드 앞에 'static'을 붙여야 한다!!!!!!!
JVM의 메모리 구조
- 메서드 영역 : 프로그램 실행 중 어떤 클래스가 사용되면, JVM은 해당 클래스의 클래스 파일을 읽어서 분석하여 클래스에 대한 정보(클래스 변수 포함)를 이곳에 저장한다.
- 힙 : 인스턴스가 생성되는 공간. 프로그램 실행 중 생성되는 모든 인스턴스는 모두 이곳에 저장된다.
- 호출 스택 : 메서드의 작업에 필요한 메모리 공간을 제공한다.
기본형 매개변수와 참조형 매개변수
- 기본형 매개변수 : 변수의 값을 읽기만 할 수 있다.
- 참조형 매개변수 : 변수의 값을 읽고 변경할 수 있다.
++ 반환 타입이 참조형이라는 것은, 메서드가 객체의 주소를 반환한다는 것을 의미
클래스 메서드와 인스턴스 메서드
- 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통적으로 사용해야 하는 것에 static을 붙인다.
- 클래스 변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
- 클래스 메서드는 인스턴스 변수를 사용할 수 없다.
- why? 클래스 메서드는 인스턴스의 생성 없이 호출이 가능하므로 클래스 메서드가 호출되었을 때 인스턴스가 존재하지 않을 수도 있다. 그래서 클래스 메서드에서 인스턴스 사용을 금지한다.
- 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.
- why? static을 붙이면 메서드 호출 시간이 짧아지므로 성능이 향상된다.
class MyMath2{
long a, b;
// 인스턴스변수 a, b만을 이용해서 작업하므로 매개변수가 필요없다.
long add() { return a + b; } // a, b 는 인스턴스 변수
long subtract() { return a - b; }
long multiply() { return a * b; }
double divide() { return a / b; }
// 인스턴스변수와 관계없이 매개변수만으로 작업이 가능하다.
static long add(long a, long b) { return a + b; } // a, b 는 지역변수
static long subtract(long a, long b) { return a - b; }
static long multiply(long a, long b) { return a * b; }
static double divide(double a, double b) { return a / b; }
}
public class MyMathTest2 {
public static void main(String[] args) {
// 클래스메서드 호출
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(200.0, 100.0));
// 인스턴스 메서드는 객체생성 후에만 호출이 가능함.
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());
}
}
클래스 멤버와 인스턴스 멤버 간의 참조 호출
클래스 멤버는 언제나 참조 또는 호출이 가능하기 때문에 인스턴스 멤버가 클래스 멤버를 사용하는 것은 문제없다. 하지만 인스턴스 멤버는 반드시 객체를 생성한 후에만 참조 또는 호출이 가능하기 때문에 클래스 멤버가 인스턴스 멤버를 참조, 호출하기 위해서는 객체를 생성해야만 한다.
'Book > 자바의 정석' 카테고리의 다른 글
[자바의 정석] Chapter 7. 객체지향 프로그래밍 II - 추상메서드, 인터페이스 (0) | 2023.07.14 |
---|---|
[자바의 정석] Chapter 7. 객체지향 프로그래밍 II - 오버라이딩, 접근 제어자, 다형성 (0) | 2023.07.14 |
[자바의 정석] Chapter 6. 객체지향 프로그래밍 I - 오버로딩, 생성자 (0) | 2023.07.14 |
[자바의 정석] Chapter 5. String 배열, 다차원 배열 (0) | 2023.07.14 |
[자바의 정석] Chapter 5. 배열(Array) (0) | 2023.07.14 |