본문 바로가기
Learning-log/JAVA

패키지, import, 캡슐화, 접근제한자, 접근자, 설정자, static, JVM 메모리 구조 (Java)

by why제곱 2023. 4. 1.

접근 제한자

접근제한을 할 때 패키지로도 접근제한 가능

 

패키지

  • 프로그램의 많은 클래스를 관리하기 위해 패키지 이용(컴퓨터의 폴더와 비슷)
  • 패키지는 클래스와 관련있는 인터페이스를 모아두기 위한 이름 공간(Name Space)
  • 패키지 구분은 .(dot) 연산자 이용 (컴퓨터에서 하위폴더 나타낼 때 \쓰는 것과 유사)
  • 패키지 이름은 시중에 나와 있는 패키지들과 구분되게 지어야함
    • why ? 수백만개의 회사의 수많은 프로젝트들의 클래스 이름이 중복될 수 있기 때문에 패키지로 구분
    • 일반적으로 도메인.프로젝트이름.모듈이름
    • ex. com.ssafy.project_이름.module_이름
  • 일반적으로 소속이나 회사의 도메인 사용
  • 중첩 가능(마치 컴퓨터의 하위폴더가 있듯이!)

ex. List 사용 시 java.awt 안에 들어가 있는 것과 java.util 안에 들어가 있는 것으로 나뉨. 이 둘은 이름이 같아서 같은 것이라 생각할 수도 있지만 다른 패키지 내에 있으므로 다른 것.

  • 패키지의 장점
    • 정리정돈이 잘 됨.
    • 패키지 단위로 접근제어 가능
    • 클래스를 유일하게 구분 가능.(구별)

 

임포트(Import)

  • 다른 패키지에 있는 클래스를 사용하기 위해 필요
  • import 선언 시, import 키워드 뒤에 package 이름과 클래스 이름을 모두 입력하거나, 해당 패키지의 모든 클래스를 포함할 때는 * 사용
  • *은 해당 패키지의 모든 클래스를 import 하겠다는 의미
package day230119.pkg1;
import day230119.pkg1.pkg2.pkg3.person
public class PackageTest {
		publie static void main(String[] args ) {
				person p1 = new person(); 
//import한 패키지에 있는 person이라는 클래스로 객체를 찍어낸 것
package day230119.pkg1;
import day230119.pkg1.pkg2.pkg3.person
import day231109.pkg1.pkg2.person
public class PackageTest {
		publie static void main(String[] args ) {
				day231109.pkg1.person p1 = new day230119.pkg1.person();
				day231109.pkg1.pkg2.person p1 = new day230119.pkg1.pkg2.person();
				day231109.pkg1.pkg2.pkg3.person p1 = new day230119.pkg1.pkg2.pkg3.person(); 
//각 다른 패키지에 있으나 이름이 같은 클래스를 사용하고 싶다면
//패키지를 생략할 수 없다. "패키지명.클래스명" 써주기 (풀패키지 이름)

 

캡슐화

  • 객체의 속성과 행위를 하나로 묶고 실제 구현 내용 일부를 외부에 감추어 은닉
  • 캡슐화가 필요한 이유
    • 데이터가 의도치 않게 변경되는 불상사 발생 가능
    • 다른 팀원이 해당 데이터에 접근할 수 없도록 제한이 필요한 상황이 있음
    • ⇒이를 위해 접근제한자 사용.

 

접근 제한자

  • 클래스, 멤버 변수, 멤버 메소드 등의 선언부에서 접근 허용범위를 지정하는 역할의 키워드
  • 객체a가 객체b의 변수나 메소드에 접근할 수 있을 지를 결정함
  • 종류
    • public : 모든 위치에서 접근 가능
    • protected : 같은 패키지에서 접근 가능, 다른 패키지 접근 불가, 단 다른 패키지의 클래스와 상속관계 있을 경우 접근 가능
    • default : 같은 패키지에서만 접근 허용, 접근제한자가 선언이 안되었을 경우 기본 적용
    • private : 자신의 클래스에서만 접근 가능, 가장 보수적
    • 클래스(외부) : public, default // 이 두가지만 사용 가능
    • 내부 클래스(중첩), 멤버 변수, 메소드 : 4가지 모두 가능
  • 그 외
    • static : 클래스 레벨의 요소 설정
    • final : 더 이상 수정할 수 없게 함
    • abstract : 추상 메소드 및 추상 클래스 작성

 

접근자 /설정자

  • 클래스에서 선언된 변수 중 접근 제한에 의해 접근할 수 없는 변수의 경우 다른 클래스에서 접근할 수 없기 때문에 ,접근하기 위한 메서드(설정자와 접근자)를 public으로 선언하여 사용
  • 접근자와 설정자를 사용할 때의 장점
    • 데이터를 바로 수정하는 건 오류의 가능성이 높은데, 이를 방지할 수 있음.
      • 왜 오류의 가능성이 높을까? 이상한 값이 들어갈 수 있음. 메소드로 수정하면 if문 등을 활용해 이를 한번 필터링 할 수 있음.
  • private 변수의 경우 다른 클래스에 접근할 수 없음. 대신 이에 접근하기 위해 메소드를 public으로 선언 ! 이게 바로 접근자와 생성자.
  • 설정자(setter) : 값을 변경시키는 것 , set + 멤버변수 이름
  • 접근자(getter) : 값을 조회하는 것, get + 멤버변수 이름
  • 생성 방법
    • 마우스 우클릭 → Source → generate getters and setters → 원하는 변수 선택 후 확인
public class Person {
	private String name;
	private int age;
	private boolean hungry; //private인 변수 ! 
//접근자와 설정자
	public String getName() { //name의 접근자
		return name;
	}
	public void setName(String name) { //name의 설정자
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public boolean isHungry() {
		return hungry;
	}
	public void setHungry(boolean hungry) {
		this.hungry = hungry;
	}

 

싱글턴 패턴

  • 소프트웨어 디자인 패턴에서 싱글턴 패턴을 따르는 클래스는 생성될 수 있는 객체는 단 하나이고, 최초 생성 이후에는 아무리 생성자를 호출해도 최초의 생성자가 생성한 객체만이 존재해서 그 객체를 리턴.
  • 클래스를 만들면 보통 객체를 무한히 찍어낼 수 있지만 싱글턴 패턴은 그걸 무한히 찍어내지 않고 딱 하나의 객체만 찍어낼 수 있도록 제한을 거는 것.
  • 객체가 하나만 필요한 경우에 사용. 객체를 여러 개 만들면 데이터가 여러 개로 분리가 되는데 하나의 객체에 모든 데이터를 모아 놓고 싶은 경우
  • 객체를 하나만 만들어서 두루 두루 사용하고 싶을 수도!
  • 만드는 방법
    1. private로 자기 자신 만들기
    2. 생성자를 private으로 하여 막기
    3. 유일한 객체에 접근할 수 있는 통로 만들기
    public class Person {
    	//1. private으로 자기 자신을 만들기
    	private static Person instance = new Person();
    	//왜 static? 객체를 생성하지 않고 클래스 이름으로 접근하기 위해서
    	
    	//2. 생성자를 private로 막기
    	private Person() {
    		this.name = "유일한 사람";
    		this.age = 12313;
    	}
    	// 3. 유일한 객체에 접근할 수 있는 통로 만들기
    	public static Person getInstance() {
    		return instance;
    	} //=> 싱클톤으로 바꾼 것.
    
  • 싱글톤 패턴으로 만들면 해당 객체에 접근할 수 있는 통로를 만들기 위해 접근자를 public으로 !

 

JVM 메모리 구조

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

 

static 특징

  • 클래스 영역에 클래스 정보가 등록될 때 클래스의 이름으로 만들어지는 것들.
  • static이 붙으면 클래스 변수, 안 붙으면 인스턴스 변수
  1. 로딩 시점
    • static : 클래스 로딩 시
    • non-static : 객체 생성시 : 실제 instance를 만들 때 heap영역에 instance가 만들어질 때 만들어지는 것
    • static이 붙으면 도장이 안 찍혀! 그 자체로 존재함.
    • static이 안 붙으면 도장이 찍히기 전까지는 존재 안 하다가 찍히면 객체 내에 존재.
    • ⇒ 필드나 메소드를 객체마다 다르게 가져야 하면 non-static으로, 객체 생성 없이 사용할 수 있는 필드와 메소드를 원한다면 static으로!
  2. 메모리상의 차이
    • static : 클래스당 하나의 메모리 공간만 할당 ⇒ 도장 찍을 땐 안 찍히고, 선언할 때 생기니까
    • non-static : 인스턴스 당 메모리가 별도로 할당 ⇒ 왜? 도장이 찍힐 때마다 객체에 찍히니까!
  3. 문법적 특징
    • static : 클래스 이름으로 접근
    • non-static : 객체 생성 후 접근
  4. static영역에서 non-static 직접 접근 불가(사용 불가)
  5. WHY? static은 객체를 참조하지 않고 사용하고, non-static은 instance가 생긴 후에야 사용 가능하므로 인스턴스 필드나 메소드, this 키워드 사용불가.
  6. non-static 영역에서는 static영역에 대한 접근 가능
  •