230720

객체지향 프로그래밍 (2) - 객체

JVM 메모리 구조


JVM 메모리 구조

  • Java 언어는 메모리 관리를 개발자가 하지 않음
  • GC (Garbage Collection) 가 메모리 관리

객지프1

Garbage Collection

  • Heap 영역 (class 영역 포함) 에 생성된 메모리 관리 담당
  • 더이상 사용되지 않는 객체들을 점검하여 제거
  • 자동적 실행/CPU가 한가 or 메모리 부족
  • JVM에 의해서 실행
  • System.gc() 를 통해 호출 (시스템 영향을 줘서 하지 않기…)

객체 생성과 메모리 할당

Person p1 = new Person();
p1.name = "Yang";
p1.age = 45;
p1.hobby = "유튜브";

클래스 영역 = 메소드 영역: 클래스 안에 있는 메소드가 들어가기 때문에 메소드 영역이라고도 함

객지프2

static 특징

대체 미리 쓸 수 있다는 게 무슨 말임?????? static으로 선언하면 설계도에 같이 넣어서 이전에~~ non-static은 그때그때 선언할 때마다 할당된다.

  1. 로딩 시점
  • static: 클래스 로딩 시…
  • non-static: 객체 생성 시
  1. 메모리 상의 차이
  • static: 클래스당 하나의 메모리 공간만 할당 → 미리 class를 선언하기 때문에 class 안에 인스턴스들을 할당해서 메모리 공간 차지가 적음
  • non-static: 인스턴스 당 메모리가 별도로 할당 → 인스턴스 하나마다 메모리 각각 할당
  1. 문법적 특징
  • static: 클래스 이름으로 접근
  • non-static: 객체 생성 후 접근

    public class Person {
    	static int pCount;
    
    	String name;
    	int age;
    	String hobby;
    }
    
    public class PersonTest {
    	public static void main(String[] args) {
    		Person p new Person();
    		p.name = "Kim";
    		Person.pCount ++;
    
    		p.pCount++; //오류는 나지 않지만 경고... 무슨 말임??
    }
    

    왜 인스턴스가 아니라 클래스 이름으로 접근하는 것을 권장할까? static → 인스턴스 생성 없이 접근할 수 있는 공유 메모리여서? 여러개의 인스턴스가 생성되어 있을 때는 어떻게 할까? 인스턴스로 접근해도 노란 줄 없음~~

  1. static 영역에서는 non-static 영역을 직접 접근이 불가능

    public class Main {
    	String str = "문장";
    
    	public static void main(String[] args) {
    		System.out.println(str);
    	}
    }
    

    static: 미리 메모리에 올라가 있어서 인스턴스 생성 여부 관계 X

    non-static: 인스턴스가 만들어져야 쓸 수 있는 것, 만들어지기 전까지 메모리에 올라가지 않기 때문에 static에서는 접근할 수 없음 (당연한 말..)

  2. non-static 영역에서는 static 영역에 대한 접근이 가능

    public class Main {
    	static String str = "문장";
    
    	public void print() {
    		System.out.println(str);
    	}
    }
    

    non-static을 실행할 때 static 영역에 해당하는 것들은 이미 올라가 있기 때문에 접근할 수 있음

접근 제한자


패키지

패키지

  • PC의 많은 파일을 관리하기 위해서 폴더를 이용한다
  • 프로그램의 많은 클래스를 관리하기 위해서 패키지를 이용한다
  • 패키지는 클래스와 관련 있는 인터페이스들을 모아두기 위한 이름 공간
  • 패키지의 구분은 .(dot) 연산자를 이용한다 pkg1.pkg2.pkg3 : pkg1 안에 pkg2 안에 pkg3 객지프3 pkg1 에서 main을 실행하더라도 import pkg1.pkg2.Person; 해서 pkg1의 Person을 사용하는 것이 아닌 pkg2의 Person을 사용할 수 있다 만약 둘 다 쓰고 싶다면?
    import pkg1.pkg2.Person;
    import pkg1.Person;
    

    내부적으로 같은 이름의 클래스이지만 다른 친구를 사용할 수는 없을까? → 풀패키지명으로 자료형을 적어주면 된다.

    pkg1.Person p1 = new pkg.Person;
    pkg1.pkg2.Person p2 = new pkg1.pkg2.Person();
    pkg1.pkg2.pkg3.Person p1 = new pkg1.pkg2.pkg3.Person();
    

    하지만 이렇게 하기 너무 불편하기 때문에… **같은 이름을 쓰는 것을 지양합시다~!**

  • 패키지의 이름은 시중에 나와 있는 패키지들과 구분되게 지어야 한다
  • 일반적으로 소속이나 회사의 도메인을 사용한다. com.name.project_이름.module_이름

임포트

임포트

  • 다른 패키지에 있는 클래스를 사용하기 위해서는 import 과정이 필요하다 객지프4
    package com.name.project.service;
    import com.name.project.dto.Person;
    public class PersonService {
    	Person p;
    }
    
  • PersonService.java에서 Person 클래스를 사용하기 위해서는 import 해야 한다.
  • import를 선언할 때는 import 키워드 뒤에 package 이름과 클래스 이름을 모두 입력하거나, 해당 패키지의 모든 클래스를 포함할 때는 ‘*’를 사용하기도 한다.
    import package_name.class_name;
    import package_name.*; // *: 모두 가져오라는 뜻
    

    ★ 하위 패키지에 있는 것들은 다른 공간의 친구들이라 가져올 수 없어! 하위 패키지에 접근하고 가져와야 함

캡슐화 (Encapsulation)

public class Person {
	public String name;
	public int age;
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public void eat() {
		System.out.println("음식을 먹는다.");
	}
}

Person p = new Person ("김싸피", 28);

객지프5

이런 일이 가능한 이유는 무엇일까?

캡슐화

  • 객체의 속성(data fields)과 행위(메서드, methods)를 하나로 묶고
  • 실제 구현 내용 일부를 외부에 감추어 은닉한다 객지프6

접근 제한자 (access modifier)

객지프7

  • 클래스, 멤버 변수, 멤버 메서드 등의 선언부에서 접근 허용 범위를 지정하는 역할의 키워드
  • 접근 제한자의 종류
    • public: 모든 위치에서 접근 가능
    • protected: 별로 사용할 일이 없을 것이에요 → 같은 패키지 - 접근 가능 → 다른 패키지 - 불가능 → 단, 다른 패키지의 클래스와 상속관계가 있을 경우 접근 가능
    • (default) → 같은 패키지 - 접근 허용 → 접근제한자가 선언이 안 되었을 경우 기본 적용
    • private → 자신 클래스에서 접근 허용 클래스(외부) 사용 가능: public, default 내부 클래스, 멤버변수, 메소드 사용가능: 4가지 모두 가능
  • 그 외 제한자
    • static: 클래스 레벨의 요소 설정
    • final: 요소를 더 이상 수정할 수 없게 함
    • abstract: 추상 메서드 및 추상 클래스 작성
수식어클래스 내부동일 패키지(다른 패키지 내의) 
하위 클래스다른 패키지   
privateO   
(default)OO  
protectedOOO 
publicOOOO

접근자(getter) / 설정자(setter)

  • 클래스에서 선언된 변수 중 접근제한에 의해 접근할 수 없는 변수의 경우 다른 클래스에서 접근할 수 없기 때문에 접근하기 위한 메서드(설정자와 접근자)를 public으로 선언하여 사용

    public class Person {
    	private String name;
    	private int age;
    
    	//접근자
    	public String getName() {
    		return name;
    	}
    
    	//설정자
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	//접근자, boolean 타입의 getter는 is를 쓰는 것이 국룰~ isHungry~
    	public int getAge() {
    		return age;
    	}
    
    	//설정자
    	public void setAge(int age) {
    		this.age = age;
    	}
    

객체 배열 관리


싱글턴 패턴 (Singleton Pattern)

객체가 딱 하나만 필요할 때!!

  • 소프트웨어 디자인 패턴에서 싱글턴 패턴(Singleton pattern)을 따르는 클래스는 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴

    public class Manager {
    	//외부에서 생성하지 못하게 막아버림!11 생성자에 private을 걸어버령
    	//기본 생성자를 작성하고 접근 제한자를 private으로 만들어
    	private static Manager manager = new Manager();
    	//가지고 있고 싶을 때
    	private Person () {};
    	private Person instance = new Person();
    	//이렇게 선언하는 것도
    	private String name = "Yang";
    	//이런 식으로 선언하는 거랑 같음
    
    	//외부에서 나의 instance에 접근해서 사용할 수 있게 하는 메소드
    
    	public Person getInstance() {
    		//미리 선언하지 않고 이런 식으로 조건문을 활용해서, instance가 존재하지 않을 경우 -> 만들어서 return
    	//	if (instance == null)
    	//		instance = new Person()
    		return instance;
    	}
    
    	private Manager() {}
    	public static Manager getManager() {
    		return manager;
    	}
    }
    

    //static으로 미리 올려 놓는다면? –> public static … -> instance 변수를 가져올 수 없기 때문에 에러 남 → private static Person 로 instance도 static으로 미리 선언해야 됨

    main
    Person p1 = Person.getInstance();
    Person p2 = Person.getInstance();
    

    여기서 p1과 p2는 같은가? **YES** 객지프8 같은 인스턴스 값을 가져오기 때문에! (singleton의 경우에만 해당되는 듯)

객체 배열 관리

객체 배열 관리란?

  • 정보 관리 시스템 ex) 학사 관리 시스템
  • 캡슐화를 이용하여 클래스 작성
  • DB 대신 배열을 사용해 객체의 정보를 저장
  • 객체의 조회, 추가, 수정, 삭제(CRUD)를 구현
  • 싱글턴 패턴을 사용하여 정보 관리 일원화