객체의 개념
- 소프트웨어 객체는 현실 세계의 객체를 필드와 메서드로 모델링한 것
- 소프트웨어 객체는 상태를 필드(Field)로 정의하고, 동작을 메서드(Method)로 정의.
- 필드는 객체 내부에 선언된 변수를 의미하고, 메서드는 객체 내부에 정의된 동작
절차 지향 프로그래밍
- 일련의 동작을 순서에 맞추어 단계적으로 실행하도록 명령어를 나열
- 데이터를 정의하는 방법보다는 명령어의 순서와 흐름에 중점
- 수행할 작업을 예상할 수 있어 직관적인데, 규모가 작을 때는 프로그래밍과 이해하기가 용이
- 소프트웨어는 계산 위주이므로 절차 지향 프로그래밍이 적합
객체 지향 프로그래밍
- 소프트웨어의 규모가 커지면서 동작과 분리되어 전 과정에서 서로 복잡하게 얽혀 있는 데이터를 사용했기 때문에 절차 지향 프로그래밍 방식의 한계
- 절차 지향 프로그램은 추후 변경하거나 확장하기도 어려움
- 현실 세계를 객체 단위로 프로그래밍하며, 객체는 필드(데이터)와 메서드(코드)를 하나로 묶어 표현
- 객체지향언어 = 프로그래밍 언어 + 객체지향개념(규칙)
- Object Oriented Programming(OOP)
- 캡슐화, 상속, 추상화, 다형성
객체의 상호작용
현실세계의 모든 현상은 객체와 객체간의 상호작용으로 이루어져 있다.
객체간의 관계
- 사용관계 - 다른 객체의 필드를 읽고 변경하거나 메소드를 호출하는 관계
- 상속관계 - 부모와 자식 관계
- 집합관계 - 완성품과 부품의 관계
객체와 클래스
- 클래스 - 객체를 정의해 놓은 것으로 객체를 생성하는데 사용
- 객체 - 실제로 존재하는 것, 사물 또는 개념으로 객체가 가지고 있는 기능과 속성에 따라 용도가 다름
특징
-캡슐화: 관련된 필드와 메서드를 하나의 캡슐처럼 포장해 세부 내용을 외부에서 알 수 없도록 감추는 것
- 필드와 동작을 하나로 묶고 실제 구현 내용을 외부에 감추는 것
- 외부의 잘못된 사용으로 인해 객체가 손상되지 않도록 하지 위함
- 접근 제어자(public , private)를 사용해서 캡슐화된 멤버를 노출시킬 것인지 숨길것인지를 결정
- 상속: 자녀가 부모재산을 상속받아 사용하듯이 상위 객체를 상속받은 하위 객체가 상위 객체의 매서드와 필드를 사용하는 것
- 상속은 개발된 객체를 재사용하는 방법 중 하나, 유지보수 시간을 최소화시켜줌
- 다형성 : 대입되는 객체에 따라서 메서드를 다르게 동작하도록 구현하는 기술. 실행 도중 동일한 이름의 다양한 구현체 중에서 매서드를 선택 가능
- 사용방법은 동일하지만 실행결과가 다양하게 나오는 성질
- 자동차의 부품에 해당하는 객체를 교환하면 같은 사용법이라도 실행성능이 다르게 나올 수 있음.
- 추상화
현실 세계의 객체는 수많은 상태가 있고 다양한 동작을 하지만, 클래스에 모두 포함하기는 어렵기에 추상화(Abstraction)하는 과정이 필요
추상화는 현실 세계의 객체에서 불필요한 속성을 제거하고 중요한 정보만 클래스로 표현하는 일종의 모델링 기법
따라서 사람마다 추상화하는 기법이 같지 않으므로 각 개발자는 클래스를 다르게 정의 가능
클래스 선언
- 형식
class 클래스이름 {
// 필드
// 메서드
}
// EX
public class Ball {
double radius = 2.0;
double getVolume () {
return 4 / 3 * 3.14 * radius * radius * radius;
}
}
- 클래스 선언과 파일
- 보통 소스파일마다 하나의 클래스를 선언하지만, 2개 이상의 클래스를 하나의 파일로 선언 가능
- 하나의 파일에 클래스가 둘 이상 있다면 하나만 public으로 선언할 수 있고, 해당 클래스 이름은 소스 파일 이름과 동일해야 함
// Ball.java
public class Ball { }
class Cylinder { }
- 클래스의 구성 요소
- 멤버
- 필드
- 메서드
- 생성자
- 참고
- 지역 변수는 메서드 내부에 선언된 변수
- 매개 변수도 일종의 지역 변수임
- 멤버
변수의 종류 | 선언위치 | 생성시기 | 메모리 위치 |
클래스 변수 | 클래스 영역 | 클래스가 메모리에 올라갈때 | Method 영역 |
인스턴스 변수 | 인스턴스가 생성되었을때 | Heap 영역 | |
지역 변수 | 블럭내부 | 변수 선언문이 수행되었을때 | Heap 영역 |
JVM 런타임 데이터 영역
메서드 영역 | 스택 영역 | 힙 영역 |
프로그램실행코드 | method2 frame 지역변수 매개변수 method1 frame 지역변수 매개변수 |
객체 1 객체 2 객체 3 |
static 영역 | ||
상수 풀 |
클래스 변수
- static을 붙이며, 클래스가 메모리에 로딩될 때 생성된다. JVM메모리 영역 중 Method 영역에 로드된다.
- 모든 클래스의 객체가 공통된 변수를 공유한다.
- 이미 메모리에 올라가 있어서 클래스의 객체를 생성하지 않고도 사용 가능하다
인스턴스 변수
- 클래스의 객체를 생성할 때 만들어지며, JVM 메모리 영역 중 Heap 영역에 로드된다.
- 클래스의 객체마다 독립적인 값을 가질 수 있다.
지역 변수
- 블럭 내부에서 변수 선언문이 실행되었을 때 생성된다.(초기화 블록)
- 블럭이 종료되면 소멸된다
- JVM메모리 영역중 Heap영역에 로드된다.
참고 - 자바의 메모리 구조
- 1) PC Register - 현재 수행중인 JVM명령어 저장
- 2) JVM stack - 호출된 메소드의 매개변수, 지역변수, 리턴정보 저장
- 3) Native Method stack - 자바 외 C, C++로 구현된 정보 저장
- 4) Heap : 런타임 중 생성되는 객체들이 저장
- 5) Method :전역변수, 정적(Static)변수, 메소드 정보 저장
- >>> 가비지 컬렉션 : Garbage Collector가 주기적으로 더 이상 사용하지 않는 메모리를 수집하고 해제하는 역할을 함
- >>> Heap 영역과 달리, Method 영역에 저장된 정보는 가비지 컬렉션의 대상이 되지 않으며, 프로그램이 종료될 때 해제
Runtime Data Area | ||||
Method | Heap | PC Register | JVM stack | Native Method Stack |
필드와 지역 변수의 차이
- 필드는 기본 값이 있지만, 지역변수는 기본값이 없어 반드시 초기화
- 필드는 클래스 전체에서 사용할 수 있지만 지역변수는 선언된 블록 내부의 선언된 후에만 사용 가능
필드와 메서드 접근
- 클래스 내부에서 자신의 멤버에 접근하려면 참조 변수 this 혹은 참조 변수 없이 그냥 멤버 이름 그대로 사용하면 됨
- 예를들어 외부 클래스 Circle의 객체 myCircle이 있다면 myCircle 객체의 radius와 findArea()는 다음과 같은 방식으로 접근
접근자(겟터)와 설정자 (셋터)
- 필요성
- 클래스 내부에 캡슐화된 멤버를 외부에서 사용할 필요
- 접근자와 설정자
- private으로 지정된 필드의 값을 반환하는 접근자와 값을 변경하는 설정자는 공개된 메서드
- 일반적으로 접근자는 get, 설정자는set으로 시작하는 이름을 사용
- 필드 이름을 외부와 차단해서 독립시키기 때문에 필드 이름 변경이나 데이터 검증도 가능
UML (Unified Modeling Language)
- 1997년 OMG(Object Management Group)에서 표준으로 채택한 통합 모델링 언어
- 모델을 만드는 표준언어
- UML 다이어그램을 그리며 모델을 만드는 일은 개발보다 비용이 적게 들긴 하지만, 훨씬 적게 드는것이 아님. 때로는 개발보다 비용이 더 많이 들수도 있음.
- UML을 사용하는 3가지 유형
- 다른 사람들과의 의사소통 또는 설계논의
- 전체 시스템의 구조 및 클래스의 의존성 파악
- 유지보수를 위한 설계의 backend 문서
생성자
- 생성자의 의미와 선언
- 생성자의 역할 : 객체를 생성하는 시점에서 필드를 다양하게 초기화
//생성자 선언방식
클래스이름 (){} // 일반적으로 공개되므로 public으로 선언되지만 아닐 수도 있음.
// 생성자 사용
클래스이름 변수 = new 클래스이름();
/*
* 생성자 이름은 클래스 이름과 같다.
* 생성자의 반환 타입은 없다.
* 생성자는 new연산자와 함께 사용하며, 객체를 생성할 때 호출한다.
* 생성자도 오버로딩할 수 있다.
*/
- 디폴트 생성자
- 모든 클래스는 최소한 하나의 생성자가 있음
- 만약 생성자를 선언하지 않으면 컴파일러가 자동으로 디폴트 생성자를 추가
class Circle {
private double radius;
public double getRadius(){}
public void setRadius(double radius){}
}
public class CircleDemo {
public static void main(String[] args){
Circle myCircle = new Circle();
}
}
생성자 오버로딩
- 생성자도 메서드처럼 오버로딩 가능
class Circle {
double radius;
String color;
public Circle(double r, String c){
radius = r;
color = c;
}
public Circle(double r){
radius = r;
color = "Blue";
}
public Circle(String c){
radius = 10.0;
color = c;
}
public Circle(){
radius = 10.0;
color = "Red";
}
}
- this와 this()
class Square{
private double side;
public void setRadius(double s){
side = s;
}
}
class Square {
private double side;
public void setRadius(double side) {
this.side = side;
}
}
- 연속 호출
// 예를 들어 반환 타입이 void인 setName(String name), setAge(), sayHello()라는 메서드를 가진
// Person 클래스가 있다고 가정
Person person = new Person();
person.setName("hoho");
person.setAge("100");
person.sayHello();
// setName()과 setAge()의 반환이 this라면
Person person2 = new Person();
person2.setName("hoho").setAge(200).sayHello();
- 인스턴스 멤버와 정적 멤버
- 자바는 static 키워드로 클래스의 필드를 공유할 수 있도록 지원
- 인스턴스 변수 : static키워드로 지정되지않아 공유되지 않는 필드로 인스턴스마다 자신의 필드를 생성
- 정적 변수 혹은 클래스 변수 : static 키워드로 지정하여 모든 인스턴스가 공유하는 필드
- 인스턴스 변수는 객체 별로 관리, 객체를 생성할 때 인스턴스 변수도 생성되고 객체가 소멸될 때는 자동으로 소멸
- 반면 정적 변수는 클래스 로더가 클래스를 메서드 영역에 적재할 때 생성
- 정적 메서드의 유의 사항
- 객체와 관련된 인스턴스 변수를 사용할 수 없다.
- 객체와 관련된 인스턴스 메서드를 호출할 수 없다.
- 객체 자신을 가리키는 this 키워드를 사용할 수 없다.
- 정적 멤버의 활용
클래스이름.정적변수이름
클래스이름.정적메서드이름()
- 상수는 변경되지 않는 변수이기 때문에 final 키워드로 지정하지만, final로만 지정하면 객체마다 자신의 기억공간.
- 상수는 값이 변경되지 않으므로 객체마다 따로 기억 공간을 할당할 필요가 없다. 따라서 static final로 지정해서 선언
static final 데이터형 상수 = 초깃값;
- 정적 블록
- 정적변수의 초기화 과정이 for 문이나 오류 처리처럼 복잡하다면 과정이 그리 간단하지 않을 것이다. 대신에 정적변수의 초기화가 복잡할 때는 다음과 같이 정적 블록을 사용할 수 있다.
- Object클래스
- 자바에서 모든 클래스의 최상위 부모클래스
- 명시적으로 부모를 extends하지 않은 클래스들의 묵시적 부모가 Object라고 보면 됨
'CODING PRACTICE > Java' 카테고리의 다른 글
Java__Basic(2) (5) | 2025.08.04 |
---|---|
Java__Basic(1) (5) | 2025.08.03 |