728x90
Write Once, Run Anywhere(작성은 한 번만, 동작은 어디든)
수업
수업제목: JAVA 기반의 객체지향 프로그래밍
수업기간: 06/22(토), 06/29(토)
수업 시간: 09:00 ~ 18:00
객체와 클래스
- 객체 지향 프로그래밍(Object-Oriented Programming)
→ 반복적으로 하는 작업을 줄이기 위해서 나온 방법이다.
→ OOP is A P.I.E
- 추상화(Abstraction): 현실의 객체를 추상화 해서 클래스를 구성
- 다형성(Polymorphism): 하나의 객체를 여러 가지 타입으로 참조
- 상속(Inheritance): 부모의 클래스의 자산을 물려받은 자식을 정의하여 코드 재사용이 가능
- 은닉화(Encapsulation): 데이터를 외부에 직접 노출하지 않고 메서드를 이용해 보호
- 현실의 객체의 속성과 기능을 추상화(abstract)하여 클래스를 정의한다.
- 클래스는 구체화 되어 프로그램의 객체(instance, object)가 된다.
- Object들의 집합이 Instance 이다.
- 추상화로 클래스 만들고 구체화로 객체 사용하기
public class Person {
void eat() {
System.out.println("냠냠");
isHungry = false;
}
void work() {
System.out.println("열심히");
isHungry = true;
}
}
public class PersonTest {
public static void main(String[] args) {
Person person1 = new Person();
person1.name = "홍길동";
person1.isHungry = true;
System.out.printf("name: %s, isHungry: %b%n", person1.name, person1.isHungry);
person1.eat();
System.out.printf("name: %s, isHungry: %b%n", person1.name, person1.isHungry);
Person person2 = new Person();
person2.name = "임꺽정";
person2.isHungry = true;
System.out.printf("name: %s, isHungry: %b%n", person2.name, person2.isHungry);
System.out.printf("name: %s, isHungry: %b%n", person1.name, person1.isHungry);
}
}
- 객체의 생성과 메모리 할당
- metaspace = classArea
- stack은 call
1. call stack에서 main 메서드의 지역 변수를 값이 없이 생성
2. 클래스 정보 로딩
- static 변수 (공통 변수)
3. Heap
- 인스턴스 변수 - 객체 생성 정보
변수
멤버 변수
- 클래스 영역
- 클래스 멤버 변수 (static keyword)
- 변수의 생성: 클래스 로더에 의해 클래스가 로딩 될 때 클래스 별로 생성
개별 객체의 생성과 무관하게 모든 객체가 공유 됨 - 변수의 초기화: 타입별로 default 초리과
- 변수의 접근: 객체 생성과 무관하게 클래스 이름으로 접근
- 객체를 생성하고 객체 이름으로 접근도 가능하나 static에 부한한 표현은 아님
- Person p = new Person();
p.scientificName = "객체를 통한 변경"
Person.scientificName = "클래스를 통한 변경";
- 변수의 생성: 클래스 로더에 의해 클래스가 로딩 될 때 클래스 별로 생성
- 인스턴스 멤버 변수
- 변수의 생성: 객체가 만들어질 때 heap에 객체별로 생성됨
- 변수의 초기화: 타입 별로 default 초기화
- 변수의 접근
- 객체 생성 후(메모리에 올린 후) 객체 이름으로 접근
- 객체를 만들 때마다 객체 별로 생성(객체마다 고유한 상태 유지) - Garbage Collector에 의해 객체가 없어질 때
- 클래스 멤버 변수 (static keyword)
지역 변수
- 변수의 생성: 선언된 라인이 실행될 때
- 변수의 초기화: 사용하기 전 명시적 초기화 필요
- 변수의 접근: 외부에서는 접근이 불가능
- 소멸 시점: 선언된 영역({})을 벗어날
public class VariableTypes{
int instanceVariable; // 인스턴스 멤버 변수
static int classVariable; // 클래스 멤버 변수
}
메서드
메서드 정의와 필요성
- 메서드란?
- 현실의 객체가 하는 동작을 프로그래밍화
- 어떤 작업을 수행하는 명령문의 집합
- 메서드를 작성하는 이유
- 반복적으로 사용되는 코드의 중복 방지
- 코드의 양을 줄이고 유지 보수가 용이
선언부
- 리턴타입
- 메서드를 호출한 곳으로 반환되는 값의 타입으로 아무것도 리턴하지 않을 경우 void
- 결과를 받을 때 묵시적 형 변환 적용
- 메서드 이름은 수행하는 작업을 쉽게 파악하도록 의미 있는 이름을 사용
- 파리미터 목록
- 메서드 호출 시점에 넘겨줘야 하는 파라미터들로 넘겨줄 정보가 없는 경우 생략 가능
- 파라미터 전달 시, 묵싲거 형변환 적용
public log add(long a, long b) {
return a + b;
}
add(10L, 20L); // (O)
add(100, 200); // (O)
add(1.1, 1.2); // (X)
add(100, 200, 300); // (X)
add(100); // (X)
Variable arguments
- 메서드 선언 시, 동일 타입의 인자가 몇 개 들어올지 예상할 수 없는 경우
public static void main(String[] args) {
VariableTest vt = new VariableTest();
vt.addAll(1, 2, 3);
vt.addAll(1, 2, 3, 5);
vt.addAll(1, 2);
}
public void addAll(int... params) {
int sum = 0;
for (int i: params) {
sum += i;
}
System.out.println(sum);
}
- class 멤버와 instance 멤버 간의 참조와 호출
- 가장 중요한 것은 호출하려는 멤버가 메모리에 이쓴ㄴ가?
- 메모리에 있으면 호출 가능
- 메모리에 없으면 호출 불가
- static member
- 언제나 메모리에 있음
- 클래스 로딩 시 자동 등록
- instance member
- 객체 생성 전에는 메모리에 없음
- 객체 생성 시, 모든 일반 멤버들은 메모리에 생성
- 객체 즉, 레퍼런스를 통해 접근
- 가장 중요한 것은 호출하려는 멤버가 메모리에 이쓴ㄴ가?
오버로딩
메서드 오버로딩
- 동일한 기능을 여러 형태로 정의해야 한다면?
- 동일한 기능을 수행하는 메서드의 추가 작성
- 메서드 오버로딩의 장점
- 기억해야 할 메서드가 감소하고 중복 코드에 대한 효율적 관리 가능
메서드 오버로딩 방법
- 메서드 이름은 동일
- 파라미터의 개수 또는 순서, 타입이 달라야할 것
- 파라미터가 같으면 중복 선언 오류
- 리턴 타입 의미 없음
생성자
생성자
- 객체를 생성할 떄 호출하는 메서드 비슷한거
- new 키워드와 함께 호출하는 것
- Person person1 = new Person();
- 일반 멤버 변수의 초기화나 객체 생성 시 실행돼야 하는 작업 정리
- new 키워드와 함께 호출하는 것
- 작성 규칙
- 메서드와 비슷하나 리턴 타입이 없고 이름은 클래스 이름과 동일
생성자의 종류
- 기본 생성자(default constructor)
- 파라미터가 없고 구현부가 비어있는 형태
- 생성자 코드가 없으면 컴파일러가 기본 생성자 제공
public class DefaultPerson {
String name;
int age;
boolean isHungry;
// public DefaultPerson() {} -- 생략된 기본 생성자
public static void main(String[] args) {
DefaultPerson person = new DefaultPerson();
person.name = "홍길동";
person.age = 10;
person.isHungry = false;
}
}
- 파라미터가 있는 생성자
- 생서자의 목적이 일반 멤버 변수의 초기화
→ 생성자 호출 시, 값을 넘겨줫 초기화
- 생서자의 목적이 일반 멤버 변수의 초기화
public class DefaultPerson {
String name;
int age;
boolean isHungry;
public DefaultPerson(String n, int a, boolean i) {
name = n;
age = a;
isHungry = i;
}
public static void main(String[] args) {
DefaultPerson person = new DefaultPerson("홍길동" , 10, true);
}
}
this, this()
this
- 참조 변수로써 객체 자신을 가리킨다.
- 참조변수를 통해 객체의 멤버에 접근했던 것처럼 this를 이용해 자신의 멤버에 접근 가능
- 용도
- 로컬 변수와 멤버 변수의 이름이 동일할 경우 멤버 변수임을 명시적으로 나타냄
- 명시적으로 멤버임을 나타낼 경우 사용
public class DefaultPerson {
String name;
int age;
boolean isHungry;
// 생성자를 하나도 만들지 않는 경우, 컴파일러가 추가해준다.
public DefaultPerson() { // 기본 생성자
}
// 생성자 오버로드
// 참조의 기본원칙: 참조 위치에서 가까운 곳에 선언된 것을 우선참조
public DefaultPerson(String name, int age, boolean isHungry) {
this.name = name;
this.age = age;
this.isHungry = isHungry;
}
void walk() {
this.isHungry = true;
System.out.println("뚜벅 뚜벅");
}
}
this()
- 메서드와 마찬가지로 생성자도 오버로딩 가능
- 한 생성자에서 다른 생성자를 호출할 때 사용
- 첫 줄에서만 호출이 가능
초기화 블록
상속(inheritance)
상속
- 기존 클래스의 자산(멤버)을 자식(하위) 클래스에서 재사용하기 위한 것
- 상위 클래스의 생성자와 초기화 블록은 상속하지 않는다.
- 상위 클래스의 멤버를 물려 받기 때문에 코드의 절감
- 상위 클래스의 코드를 변경하면 모든 하위 클래스에게도 적용
- 상속의 적용
- extends 키워드 사용
Object 클래스
- 모든 클래스의 조상 클래스
- 클래스들은 extends Object가 생략됨
- 모든 클래스에는 Object 클래스에 정의된 메서드가 있다.
단일 상속(Single Inheritance)
- 자바는 단일 상속만 지원
- 대신 interface와 포함 관계로 단점 극복
- 다중 상속의 경우 여러 클래스의 기능을 물려받을 수 있으나 관계가 매우 복잡(ambiguous)해짐
- 동일한 이름의 메서드가 두 상위 클래스에게 모두 있다면 하위 클래스는 어떤 메서드를 사용할 것인가?
포함 관계
- 상속 이외에 클래스를 재활용 하는 방법
- 2개 이상의 클래스에서 특성을 가져올 때 하나는 상속, 나머지는 멤버 변수로 처리
- 상속이냐 포함이냐 그것이 문제로다.
- 어떤 클래스를 상속받고 어떤 클래스를 포함해야할까?
- 문법적인 문제는 아니며 프로젝트의 관점 문제
- 상속: is a 관계가 성립하는가? → Spiderman is a Person.
- 포함: has a 관계가 성립하는가? → Spiderman has a Spider.
오버라이딩
메서드 오버라이딩(overriding)
- 조상 클래스에 정의된 메서드를 자식 클래스에서 적합하게 수정하는 것
오버라이딩 조건
- 메서드 이름이 같아야한다.
- 매개 변수의 개수, 타입, 순서가 같아야한다.
- 리턴 타입이 같아야한다.
- 접근 제한자는 부모 보다 범위가 넓거나 같아야 한다.
- 조상보다 더 큰 예외를 던질 수 없다.
super
super 키워드
- this 통해 멤버에 접근했듯이 super를 통해 조상 클래스 멤버 접근
- 조상의 메서드 호출로 조상의 코드 재사용
변수의 scope
class Parent {
String x = "parent";
}
class Child extends Parent {
String x = "child";
void method() {
String x = "method";
System.out.println("x : " + x ); // method
System.out.println("this.x :" + this.x); // child
System.out.println("super.x :" + super.x); // parent
}
}
public class ScopeTest {
public static void main(Stringp[] args) {
Child child = new Child();
child.method();
}
}
super()
- this()가 해당 클래스의 다른 생성자를 호출하듯 super()는 조상 클래스의 생성자 호출
- 조상클래스에 선언된 멤버들은 조상 클래스의 생성자에서 초기화가 이뤄지므로 이를 재활용
- 자식 클래스에 선언된 멤버들만 자식 클래스 생성자에서 초기화
- super()는 자식 클래스 생성자의 맨 첫 줄에서만 호출 가능
- 즉, 생성자의 첫 줄엠나 this() 또는 super()가 올 수 있다.
- 명시적으로 this() 또는 super()를 호출하지 않는 경우, 컴파일러가 super() 삽입
- 결론적으로 맨 상위의 Object까지 객체가 다 만들어지는 구조
class ParCup {
int money;
public ParCup() {
}
public ParCup(int money) {
super();
this.money = money;
}
}
class ChipCup extends ParCup {
int age;
String name;
public ChipCup() {
this(3, "홍길동");
}
public ChipCup(int age) {
this(age, "홍길동");
}
public ChiCup(int age, String name) {
super();
this.age = age;
this.name = name;
}
public ChipCup(int age, String name, int money) {
super(money);
this.age = age;
this.name = name;
}
}
pacakge
자바는 동적 코딩
import java.util.*를 해도 전부 메모리에 올라가지 않는다.
사용 되지 않는 클래스는 제거 된다.
제한자(Modifier)
제한자(Modifier)
- 클래스, 변수, 메서드, 선언부에 함게 사용되어 부가적인 의미 부여
- 종류
- 접근 제한자: public, portected, default = package, private
- 그 외 제한자
- static
- final
- abstract
- synchronized
- 하나의 대상에 여러 제한자를 조합 가능하나 접근 제한자는 하나만 사용가능
- 순서는 무관
- 일반적으로 접근 제한자를 맨 앞으로
final
- 마지막, 더 이상 바뀔 수 없다.
- final class - 더 이상 확장할 수 없음: 상속금지 → 오버라이드 방지
- final method - 더 이상 재정의할 수 없음: 오버라이딩 금지
- final variable - 더 이상 값을 바꿀 수 없음(상수)
'교육 > [온라인] KOSTA EDU' 카테고리의 다른 글
[KOSTA] KAFKA with Spring - 2편 (0) | 2024.07.12 |
---|---|
[KOSTA] Kafka with Spring Boot - 1편 (0) | 2024.07.12 |
[KOSTA] 스프링 부트로 구현하는 메세징 시스템(RabbitMQ) (0) | 2024.05.24 |
[KOSTA] 도메인 모델 기반의 서비스 설계 (DDD) (0) | 2024.05.17 |
[KOSTA] 자바 코드의 성능 향상 - 2일차 (0) | 2024.02.23 |