1. 객체 지향 프로그래밍
1. 객체
- 세상에 존재하는 물체
- 식별이 가능한 것
- 속성과 행위로 구성 ( 예시) 자동차 )
- 속성 - 회사, 모델, 색상, 가격, 속도 등등
- 행위 - 가속, 브레이크, 기어변속, 조명, 경적 등등
- Java 에서는 이러한 속성과 행위를 필드와 메서드로 정의하여 구현한다. → 속성 = 필드, 행위 = 메서드
- 현실 세계에 있는 객체를 소프트웨어의 객체로 설계하는 것을 객체 모델링 이라고 한다.
2. 특징
- 캡슐화
- 속성(필드)와 행위(메서드)를 하나로 묶어 객체로 만든 후 실제 내부 구현 내용은 외부에서 알 수 없게 감추는 것
- 외부 객체에서는 캡슐화된 객체의 내부 구조를 알 수 없다. → 노출시켜 준 필드 혹은 메서드를 통해 접근 할 수 있다.
- 캡슐화 하는 이유는 외부 객체에서 해당 필드와 메서드를 잘못 사용하여 객체가 변화하지 않게 한다.
- 캡슐화된 객체의 필드와 메서드의 노출 유무는 접근제어자를 사용해 결정한다.
- 상속
- 부모 객체와 자식 객체가 존재한다.
- 부보 객체가 가지고 있는 필드와 메서드를 자식 객체에 물려주어 사용할 수 있도록 한다.
- 이유
- 객체 간의 구조를 파악하기 쉽다.
- 부모 객체에 있는 필드와 메서드를 수정하게 되면 자식 객체 전부 반영이 된다. → 일관성 유지
- 자식 객체가 부모 객체를 물려 받기 때문에 코드의 중복이 줄어들고 재사용성이 증가된다.
- 다형성
- 객체가 연산을 수행할 때 하나의 행위를 각 객체가 가지고 있는 고유한 특성에 따라 여러가지 형태로 재구성 할수 있는 것
- 추상화
- 객체에서 공통된 부분들을 모아 상위 개념으로 새롭게 선언하는 것
- 공통적이고 중요한 것들을 모아 객체를 모델링 한다.
- 객체와 클래스
- 객체를 만들기 위해 설계도에 해당하는 클래스가 필요한다.
- 클래스를 토대로 생성된 객체를 인스턴스, 이러한 과정을 인스턴스화라고 한다.
- 동일한 클래스로 여러 개의 인스턴스를 만들 수 있다.
- 클래스를 통해 만들어진 하나의 인스턴스가 여러개 모여 객체
2. 클래스 설계
- 클래스 구성은 필드, 생성자, 메서드
3. 객체 생성과 참조형 변수
- 객체 생성
- new를 사용하면 클래스로부터 객체를 생성할 수 있다.
- new 연산자 뒤에 해당 클래스의 생성자 호출 코드를 작성한다.
- 참조형 변수
- new 연사자를 통해서 객체가 생성되면 해당 인스턴스의 주소가 반환된다.
- 해당 클래스의 참조형 변수를 사용하여 받을 수 있다.
- 객체 배열
- 객체는 참조형 변수와 동일하게 취급된다.
- 배열 또는 컬렉션에도 저장하여 관리할 수 있다.
4. 객체의 속성 - 필드
객체의 데이터를 저장하는 역할
고유한 데이터, 상태 데이터, 객체 데이터로 분류할 수 있다.
- 필드의 초기값과 초기화
- 새로 정의하여 선언한 클래스의 필드들은 기본적으로 초기값을 제공하지 않을 경우 객체가 생성될 때 자동으로 기본 값으로 초기화 된다.
- '필드타입 필드명 = 값;' 으로 초기화 할 수 있다.
- 필드 타입별 기본값
데이터 타입 | 기본값 |
byte | 0 |
char | \u0000(공백) |
short | 0 |
int | 0 |
long | 0L |
float | 0.0F |
double | 0.0 |
boolean | false |
배열 | null |
클래스 | null |
인터페이스 | null |
- 외부 접근
- 예시 - Car car = new Car();
- 예시처럼 선언했다면 참조변수 car를 이용하여 외부에서 객체 내부 필드에 접근이 가능하다.
- 내부 접근
- .(도트) 연산자를 사용하여 접근할 수 있다.
- 객체 내부 메서드에서도 내부 필드에 접근할 수 있다.
5. 객체의 행위 - 메서드
객체의 행위를 뜻한다.
객체간의 협력을 위해 사용된다.
메서드 선언 예시
리턴타입 메서드명(매개변수, ...){
실행할 코드 작성
}
- 리턴타입
- 메서드가 실행된 후 호출을 한 곳으로 값을 반환할 때 해당 값의 타입을 의미한다.
- return 리턴타입의 반환값; → 이 형식으로 작성해야 한다.
- 반환할 값이 없을 떄는 리턴타입에 void를 작서해야 한다. - 반환값이 없으므로 return문을 반드시 지정할 필요는 없다.
- 매개변수
- 메서드를 호출할 때 메서드로 전달하려는 값을 받기 위해 사용되는 변수
- 전달하려는 값이 없다면 생략가능하다.
- 가변길이의 매개변수도 선언할 수 있다. → double ... speeds의 ...을 사용하면 ,로 구분하여 개수 상관없이 전달 가능하다.
- 예시
void carSpeeds(double ... speeds) {
for (double v : speeds) {
System.out.println("v = " + v);
}
}
- 메서드 오버로딩 → 함수가 하나의 기능만 구현하는 것이 아닌 하나의 메서드 이름으로 여러기능 구현하도록 하는 기능이다.
- 오버로딩의 조건
- 메서드의 이름이 같고, 매개변수의 개수, 타입, 순서가 달라야 한다.
- 응답 값만 다른 것은 오버로딩 할 수 없다.
- 접근제어자만 다른 것도 오버로딩을 할 수 없다.
- 오버로딩은 매개변수의 차이로만 구현 할 수 있다.
- 오버로딩의 장점
- 메서드 이름 하나로 상황에 따른 동작을 개별로 정의할 수 있다.
- 메서드의 이름을 절약할 수 있다.
- 오버로딩의 조건
- 기본형 & 참조형 매개변수
- 기본형 매개변수 - 값 차제가 복사되어 넘어간다 → 지정된 변수의 원본 값이 변경되지 않는다.
- 참조형 매개변수 - 지정한 값의 주소를 복사해서 전달한다. → 원본 주소를 알 수 있기 때문에 값을 읽어오고 변경하는 것도 가능하다.
6. 인스턴스 멤버와 클래스 멤버
인스턴스 멤버 = 인스턴스 필드 + 인스턴스 메서드
- 객체를 생성해야 사용할 수 있다.
- 객체의 인스턴스 필드는 각각의 인스턴스 마다 고유하게 값을 가질 수 있다.
- 인스턴스를 통해서만 메서드가 사용될 수 있다.
클래스 멤버 = 클래스 필드 + 클래스 메서드
- Java의 클래스 로더에 의해메서드 영역에 저장되고 사용된다.
- 객체 생성 없이 바로 사용 가능하다.
- 클래스 멤버 선언
- 필드와 메서드를 클래스 멤버로 만들기 위해 static 메서드를 사용한다.
- 인스턴스마다 모두 가지고 있을 필요 없는 공용적인 데이터를 저장하는 필드를 클래스 멤버로 선언하는 것이 좋다.
- 인스턴스 필드를 사용하지 않고 실행되는 메서드가 있다면 static을 사용하여 클래스 메서드로 선언하는 것이 좋다.
- 클래스 멤버로 선언된 메서드는 인스턴스 멤버를 사용할 수 없다. → 인스턴스 멤버는 객체가 생성되어야 존재할 수 있기 때문이다.
- 인스턴스 멤버로 선언된 메서드는 클래스 멤버를 사용 할 수 있다.
- 지역변수
- 메서드 내부에 선언한 변수다.
- 메서드가 실행될때마다 독립적인 값을 저장하고 관리한다.
- 메서드 내부에서 정의될때 생성되고 메서드가 종료될 때가지만 유지 된다.
- final 필드와 상수
- final 필드
- 최종적이라는 의미를 가진다.
- 초기값이 지정되면 프로그램이 실행하는 도중에는 절대로 수정할 수 없다.
- 반드시 초기값을 지정해야 한다.
- 필드 타입 앞에 final 키워드를 추가하여 선언할 수 있다.
- 상수
- 값이 반드시 한개이다.
- 불변의 값이다.
- 인스턴스마다 상수를 저장할 필요가 없다.
- final 앞에 static 키워드를 추가하여 모든 인스턴스가 공유할 수 있는 값이 한개이며 불변인 상수를 선언할 수 있다.
- 상수는 대문자로 작성하는 것이 관례이다.
- final 필드
7. 생성자
객체가 생성될 때 호출되며 객체를 초기화 하는 역할을 수행한다.
- 기본생성자
- 선언할 떄 괄호 안에 아무것도 넣지않는 생성장
- 모든 클래스는 생성자가 하나 이상 존재한다.
- 만약 생성자를 하나도 선언하지 않았다면 컴파일러는 기본 생성자를 바이트코드 파일에 자동으로 추가시킨다.
public class Car {
public Car(String model) {} // 생성자 선언
// 생성자가 한개 이상 선언되었기 때문에 기본 생성자를 추가하지 않음.
}
public class Car {
public Car() {} // 컴파일러가 추가시켜줌
}
class Car {
Car() {} // 컴파일러가 추가시켜줌
}
- 필드 초기화
- 생성자는 객체를 초기화 하는 역할을 수행한다.
- 객체를 만들때 인스턴스마다 다른 값을 가져야 한다면 생성자를 통해서 초기화 할 수 있다.
- 인스턴스마다 동일한 데이터를 가져야 한다면 초기값을 대입하는 것이 좋다.
- 생성자 오버로딩
- 생성자를 통하여 필드를 초기화 할대 오버로딩을 적용할 수 있다.
- 오버로딩 시 개수, 타입. 순서가 동일하고 매개변수명만 다를 경우 오류가 발생한다. → 중복이 불가능하다.
8. this와 this()
- this
- this는 객체 즉, 인스턴스 자신을 표현하는 키워드다.
- 객체 내부 생성자 및 메서드에서 객체 내부 멤버에 접근하기 위해 사용할 수 있다.
- 상황에 따라 this 키워드가 필수가 될 수 있다.
- this()
- 인스턴스 자신의 생성자를 호출하는 키워드다.
- 객체 내부 생성자 및 메서드에서 해당 객체의 생성자를 호출하기 위해 사용될 수 있다.
- 중복되는 코드를 줄여줄 수 있다.
- 생성자를 호출할 때는 반드시 해당 생성자의 첫 줄에 작성되어야 한다.
9. 접근 제어자
제어자는 클래스, 변수, 메서드의 선언부에 사용되어 부가적인 의미를 부여해 준다.
접근 제어자는 단 하나만 사용할 수 있다.
- 접근 제어자
- 멤버 또는 클래스에 사용, 외부에서 접근하지 못하도록 제한한다.
- public : 접근 제한이 전혀 없다.
- protected : 같은 패키지 내에서, 다른 패키지의 자손클래스에서 접근이 가능하다.
- default : 같은 패키지 내에서만 접근이 가능하다.
- private : 같은 클래스 내에서만 접근이 가능하다.
- 사용가능한 접근 제어자
- 클래스 : public, default
- 메서드 & 멤버변수 : public, protected, default, private
- 지역변수 : 없음
- 접근 제어자를 이용한 캡슐화 (은닉성)
- 클래스 내부에 선언된 데이터를 보호하기 위해 사용한다.
- 유효한 값을 유지하도록, 함부로 변경하지 못하도록 접근을 제한하는 것이 필요하다.
- 생성자의 접근 제어자
- 인스턴스의 생성을 제한할 수 있다.
- 일반적으로 클래스의 접근 제어자와 일치한다.
- 멤버 또는 클래스에 사용, 외부에서 접근하지 못하도록 제한한다.
- Getter와 Setter
- 객체의 무결성 즉, 변경이 없는 상태를 유지하기 위해 접근 제어자를 사용하지만 외부에서 private 필드를 읽어오고 저장할 때 Getter와 Setter를 사용하여 해결할 수 있다.
- Getter
- private한 필드를 읽을 필요가 있을 때 사용한다.
- 메서드 이름의 규칙은 get + 필드이름(첫 글자는 대문자)이다.
- 사용법은 인스턴스 메서드 호출과 동일하다.
- Setter
- private한 필드를 저장하거나 수정할 필요가 있을때 사용한다.
- 메서드 이름의 규칙은 set + 필드이름(첫 글자는 대문자)이다.
- 사용법은 인스턴스 메서드 호출과 동일하다.
- Getter
- 객체의 무결성 즉, 변경이 없는 상태를 유지하기 위해 접근 제어자를 사용하지만 외부에서 private 필드를 읽어오고 저장할 때 Getter와 Setter를 사용하여 해결할 수 있다.
- 제어자의 조합
- 사용가능한 제어자
- 클래스 : public, default, final, abstract
- 메서드 : public, protected, default, private, final, abstract, static
- 멤버변수 : public, protected, default, private, final, static
- 지역변수 : final
- 주의사항
- 메서드에 static과 abstract를 함께 사용할 수 없다.
- 클래스에 abstract와 final을 동시에 사용할 수 없다.
- abstract메서드의 접근 제어자가 private일 수 없다.
- 메서드에 private와 final을 같이 사용할 필요는 없다.
- 사용가능한 제어자
10. package와 import 이해하기
- 패키지
- 클래스의 일부분이면서 클래스를 식별해준ㄴ다.
- 상위 패키지와 하위 패키지를 .(도트)로 구분한다. → package.상위패키지.하위패키지
- import
- 다른 패키지에 있는 클래스를 사용하기 위해 명시하는 키워드
- 예시 → import java.io.BufferedReader;
- 모든 클래스를 사용하려면 클래스 이름을 생략하고 * 를 사용하여 표현할 수 있다. → import java.io.*;
- 서로 다른 패키지에 있는 같은 이름의 클래스를 동시에 사용하려면 해당 클래스에 패키지 명을 전부 명시해야 한다.
'스터디일지 > JAVA' 카테고리의 다른 글
[2023.08.15] 자바 2주차 문법 강의 (0) | 2023.08.15 |
---|---|
[2023.08.14] 자바 1주차 문법 강의 (0) | 2023.08.14 |
[2023.07.31] 자바의 예외 처리 (0) | 2023.07.31 |
[2023.07.29] StringTokenizer의 메소드 / Math 함수 / Greedy Algorithm (탐욕 알고리즘) (0) | 2023.07.29 |
[2023.07.28] 요세푸스 순열 / PriorityQueue / Heap (0) | 2023.07.28 |