Home > 언어 > 자바 > java 추상화

java 추상화
java OOP

OOP


OOP 특징

  • Abstraction(추상화)
    • 현실의 객체를 추상화하여 클래스 구
  • Polymorphism(다형성)
    • 하나의 객체를 여러 타입으로 참조가능
  • Inheritance(상속)
    • 부모의 자산을 물려받아 자식에서 재정의 가능
  • Encapsulation(데이터 은닉과 보호)
    • 데이터를 외부에 노출 시키지 않고 메서드를 사용해 보호

객체

→ 주체가 아닌것, 주체를 활용하는 것을 의미

따라서 객체지향 프로그래밍은 주변의 많은 것들을 객체화 해서 프로그래밍하는 것을 의미한다.

OOP의 장점

  • 블록 형태의 모듈화된 프로그래밍
    • 신뢰성이 높다. → 검증된 객체를 사용하기 때문에
    • 추가/수정/삭제 용이하다
    • 재사용성이 높다.

객체 생성과 메모리

  • Jvm 메모리 구조
    • Method area
      • 클래스 정보 처리
      • 타입, field, method 정보
      • 상수 풀
    • Stack
      • 메서드의 실행공간
      • thread별 별도관리
      • 메스드 프레임에 로컬 변수가 쌓이는 구조
    • heap
      • 객체를 저장하기 위한 영역
      • thread에 의해 공유
      • 객체가 생성되고 Garbage collector에 의해 정리된다.

변수

  • primitive Type variable
    • 기본 8가지 type의 변수
  • reference Type variable
    • 나머지 모든 것(객체 참조)
  • 선언위치에 따른 분류
    • 클래스 영역(static keyword)
    • 클래스 영역
    • 함수 내부
    • 함수 선언부
  • 인스턴스 멤버 변수
    • 클래스 영역에 선언
    • 생성될 때 heap에 객체 별로 생성된다
    • 메모리에 올린 후 객체 이름으로 접근
    • Garbage Collector에 의해 객체가 없어질때 소멸
  • 클래스 멤버 변수
    • 클래스 {}영역에 선언, static keyword를 붙인다.
    • 클래스 로더에의해 클래스가 로딩될 때 구성
      • 개별 객체의 생성과 무관, 모든 객체가 공유한다
      • 공유변수라고 불린다.
    • 클래스 이름으로 접근하는 것이 좋다.

메서드

  • Variable arguments
    • addAll(int… params)
    • …을 이용하여 파라미터를 선언하면 호출 시 넘겨준 값의 개수에 따라 자동으로 배열 생성 및 초기화를 시행한다.
      • 이렇게 넘겨주면 함수 내부에서는 배열로 쓰이게 된다.

          void m1(int b, int... a){
              System.out.printf()
          }
        
      • a는 배열로 쓰이게 된다.

    • 이는 %d, %s,와 같은 format으로 출력을 할 때 사용한다.
  • 클래스 멤버와 instance 멤버 간의 참조와 호출
    • 가장 중요한 것 호출하려는 멤버가 메모리에 있는가?
      • 있으면 호출가능, 없으면 호출 불가(먼저 메모리에 로딩 후 사용해야 한다.)
    • static member : 언제나 메모리에 있다.
    • instance member : 객체 생성 전에는 메모리에 없다.
      • 객체 즉 레퍼런스를 통해 접근을 하게된다.
  • 메서드 호출 스택
    • 각각의 메서드 호출 시 마다 메서드 동작을 위한 메모리 상자를 하나씩 할당
    • 상자 내부에 메서드를 위한 파라미터 변수 등 로컬 구성
    • A메서드에서 새로운 메서드 B를 호출시 B실행을 위한 메모리 상자를 쌓는다.
      • stack 형식으로 메모리에 들어오고 종료시 B가 먼저 종료되어 메모리를 반납한다.
    • 레퍼런스로 넘기는 경우 값은 저장된다. 이 경우 클래스의 멤버를 넘겨주는 것도 레퍼런스로 넘겨주는 것에 포함된다.
  • 메서드 오버로딩
    • overloading: 동일한 기능을 수행하는 메서드의 추가작성
    • 메서드 이름은 기능별로 의미 있게 정한다.
    • 동일한 기능을 여러 형태로 정의를 할 때 쓰인다.
    • println()도 메서드 오버로딩을 통해 매개변수를 다르게 받아서 출력을 하게 된다.

    • 메서드 이름은 동일, 파라미터의 개수, 순서 or 타입은 달라야 할 것
    • js는 메서드 오버로딩이 지원되지 않는다.

생성자

this.

참조 변수로써 객체 자신을 가리킨다. 참조 변수를 통해 객체 멤버에 접근한 것처럼 this를 사용하여 자신의 멤버에 접근이 가능하다.

용도

로컬 변수와 멤버 변수의 이름이 동일한 경우 멤버 변수임을 명시적으로 나타낸다.

메서드와 마찬가지로 생성자도 오버로딩이 가능하다

  • 객체 생성 시 필요한 멤버 변수만 초기화를 진행 → 생성자 별 코드의 중복이 발생한다
  • 한 생성자에서 다른 생성자를 호출할 때 사용
  • 반드시 첫 줄에서만 호출이 가능하다.

초기화 블록

생성자처럼 멤버 변수의 초기화를 목적으로 한다.

{}를 사용하여 내부에 실행 코드를 작성한다.

클래스 초기화 블록은 클래스 멤버 변수의 초기화에 사용된다.

  • 클래스 초기화 블록
    • 클래스 멤버 변수의 초기화에 사용, 클래스 로딩시 1회 호출
  • 인스턴스 초기화 블록
    • 인스턴스 멤버 변수의 초기화에 사용, 생성자 코드 실행보다 먼저 호출된다.
    • 객체 생성시 마다 1회 호출

구성요소의 로딩 순서

  • Static 요소의 로딩
    1. Static 요소의 로딩 - 기본 초기화
    2. Static method 로딩
    3. Static Initializer 실행
    4. Static Method 중 main 실행
  • Instance 요소의 로딩
    1. 멤버 변수 로딩 - 기본 초기화
    2. Instance Initializer 실행
    3. 생성자 호출

강의 보충


Property와 field 차이 기억해두기

property와 field는 다르다. python, .net은 property는 있으나 java는 아니다. 변수로 불러오고 저장하는 것은 field로 저장한다고 하고 property는 java에는 setter, getter메서드를 통해 변수로 직접 저장하지 않는다.

python에서 self는 java의 this와 유사하다 python에서는 클래스를 만들고 사용할 때 자기 자신을 포함하도록 self를 선언하는데 다른 java와 js와 같은 경우에는 역사적으로 포함되어서 넘어간다고 가정해서 그렇다.

이에 관한 차이도 알면 좋다.

static 변수 대신에 클래스 변수를 많이 쓴다.

자바는 멤버 변수라는 것을 많이 쓰지 않는다. 오히려 클래스나 인스턴스 변수로 많이 활용되고 쓰이게 된다.

선언된 하나의 클래스에 대해 인스턴스를 여러 개 만드는 경우 인스턴스 멤버 변수는 여러 개이나 인스턴스 메서드는 하나이다.(이는 모든 객체가 공유한다.)

class Person {

    String name;           // 객체마다 하나

    static int count;      // 클래스당 하나

    void introduce() { }   // 클래스당 하나
}

이러한 클래스가 있고 여러 개의 인스턴스를 만든다고 하면 name은 여러 개이나 count와 introduce()는 하나만 생성이 된다.

java는 call by value만을 지원한다. 주소값을 받아서 사용하기 때문이다.

  String s = "ssafy";
  s=s.toUpperCase(); //SSAFY
  System.out.println(s); //ssafy

다른 변수들은 변경된 값이 저장되지만 string의 경우에는 변경이 되지 않는다. string은 불변이다.

자바는 문자열을 잘못 선언하면 garbage가 어마무시하게 나온다.

이렇게 직접 s += “a”를 하게 되면 뒤에 오는 문자들은 다 garbage로 처리되어서 GC가 많이 돌아가 jvm이 과부하되어 속도가 느려질 수가 있다.

StringBuilder와 stringBuffer을 사용해야 threadSafe하게 코드를 작성하는 것이 가능하다.

Object 클래스

모든 클래스의 조상클래스

별도의 extends선언이 없는 클래스들은 extends Object가 생략된다.

따라서 모든 클래스에는 Object 클래스에 정의된 메서드가 있다.

상속의 관계는 is-a 관계이다.

상속

  • 포함관계
    • 어떤 클래스를 상속받고 어떤 클래스를 포함해야 하는가?
      • 문법보다는 프로젝트 관점으로 보는 것이 중요

Sealed class

  • 봉인된 클래스로 내가 관리하는 특정 클래스에게만 상속이 가능
  • 상속계층 내에서 엄격한 제어를 통해 프로그램의 구조를 명확하게 유지하고 의도치 않은 상속으로 인한 복잡성과 혼란을 방지한다.
  • 명확한 역할과 직무 분류가 중요한 개념에서 사용한다.

  • class에 sealed 키워드를 사용하고 상속을 허락하는 클래스는 permits뒤에 나열한다.
    • sealed가 선언된 클래스는 permit를 반드시 필요로 한다.
  • 구현 클래스는 sealed, final, non-sealed 중 하나가 필요하다.

      sealed class SealedStudyGroup permits Algo,Cs,Java{
      	public void study(){
      		System.out.println  ("공부")
      	}
      }
    

final을 붙이면 상속불가, sealed 붙이면 sealed 상태에서 상속가능, non-sealed를 하면 자유롭게 상속하는 것이 가능하다.

메서드 재정의


매서드 오버라이딩(overriding)

조상 클래스에 정의된 메서드를 자식 클래스에서 적합하게 수정하는 것

public class Person{
	void jump(){
		System.out.println("두다리로 점프");
	}
	
}

public class Spider{
	void jump(){
		System.out.println("키 * 1000만큼 엄청난 점프");
	}
	
}
  • 오버라이딩 조건
    • 메서드 이름 같아야 함
    • 매개 변수의 개수, 타입, 순서가 같아야한다.
    • 리턴 타입이 같아야한다.
    • 접근 제한자는 부모보다 범위가 넓거나 같아야 한다.
    • 조상보다 더 큰 예외를 던질 수가 있다.

어노테이션

  • 사전적 의미: 주석
  • 컴파일러, JVM, 프레임워크 등이 보는 주석
  • 소스코드에 메타데이터를 삽입한 형태
    • 소스 코드에 붙여 놓은 라벨
    • 코드에 대한 정보 추가 → 소스코드의 구조 변경, 환경 설정 정보 추가 등의 작업진행
  • 기본 annotation의 예
    • @Deprecated
      • 컴파일러에게 해당 메서드가 deprecated 되었다고 알려준다.
    • @Override
      • 컴파일러한테 해당 메서드는 override한 메서드임을 알려준다.
      • @Override가 선언된 경우 반드시 super class에 선언된 메서드여야 한다.
    • @SuppressWarnings
      • 컴파일러에게 사소한 warning의 경우 신경쓰지 말라고 알려준다.

Import

다른 패키지에 선언된 클래스를 사용하기 위한 키워

ctrl+space : 어떤 클래스를 사용할지 선택하는 것이 가능

ctrl+shift +o: 이클립스에서 import 해주는 방법

제한자

클래스, 변수, 메서드 선언부에 함께 사용되어 부가적인 의미 부여

  • final class:
    • 더이상 확장 할 수 없음. 상속금지 → 오버라이드 방지
    • String class, Math class와 같이 기존에 만들어진 클래스에 대한 override를 방지하기 위해 추가한다.
  • final method
    • 이는 더 이상 재정의 할 수 없는 메서드이고 override를 방지하는데 사용한다.

접근 제한자 Access Modifier

접근제한자를 통해 다른 패키지로의 접근을 제한할 수 있다. 아무것도 안쓰는 경우는 default이고 같은 package내에서 접근은 다 가능하다.