[CS] 자바의 정석 독서 #10 - 패키지와 접근제어자

2025. 10. 2. 22:51·언어공부/Java | Kotlin

다형성 나오기 전에 접근제어자와 패키지에 대해서 다루니까 약간 쉬어가는 느낌으로

인텔리제이는 자동으로 import 해주는 기능이 있기 때문에 평소에는 import에 대해서 거의 몰랐다. 파이썬처럼 어느기능에 무엇이 있고 어떤 것을 import 해야하는지 알고있지 않았다. 이참에 배워보기


패키지

클래스와 인터페이스가 뭉탱이로 모아놓은 묶음이다. 같은 이름의 클래스더라도 다른 패키지에 있다면 사용가능하다.

클래스는 하나의 클래스파일이라면, 패키지는 여러 클래스들을 하위 디렉토리에 포함하는 하나의 디렉토리(폴더)다.

 

예를들어서 java.lang 패키지에 속한 String 클래스는 java.lang 디렉토리 내의 String.class로 만들어져있다.

그래서 대표적인 패키지인 java.lang도 JDK를 다운받으면 하나의 폴더로 저장되어 접근할 수 있다.

 

다만 나처럼 JDK를 직접 다운받지 않고 그냥 인텔리제이에서 기본제공하는 JDK를 사용하면 패키지가 다운받아지지 않는다나 뭐라나

 

선언

package 패키지명;

간단하다. 다만 패키지 선언은 단 한 번만 해야하며, 모든 클래스는 모두 어느 특정패키지에 속해있어야한다. 다만 간단한 클래스나 프로젝트의 경우 패키지선언을 하지 않을 때도 있는데, 그러면 자바가 기본제공하는 '이름없는 패키지'로 지정된다.

 

다른 클래스 파일을 호출할 때 선언된 패키지에 클래스파일이 없다면 에러가 터진다. 컴파일러가 파일의 위치를 알 수 없다

 

선언은 이렇게..

인텔리제이나 스프링 이니셜라이저로 가져온 디렉토리의 경우에는 src 하위 디렉토리에 폴더를 하나 만든 후 선언해야한다.

 

실행 전 hongikUniv 패키지를 선언하면 IDE 상에서는 hongikUniv라는 경로가 생기는데 실제 폴더에는 생기지 않는다.

이 상태에서 컴파일을 진행하면 패키지와 클래스파일이 생성된다.

 

컴파일러나 JVM이 클래스의 위치를 찾는데는 클래스패스(classpath)가 사용된다. 기본값은 현재 디렉토리가 되며, 윈도우 환경변수 수정을 통해 클래스패스를 조정할 수 있다. 다만 클래스패스를 수동으로 조작할 경우 현재디렉토리도 클래스패스에 추가해야한다.

 

클래스패스는 세미콜론을 기준으로 여러 개 선언할 수 있고 왼쪽부터 차례대로 이동해가며 클래스를 찾는다.


import

다른 패키지의 클래스를 사용하기 위해서는 패키지 이름이 포함된 클래스의 풀네임을 사용해야한다.

 

package javatest;

public class test {
    public static void main(String[] args) {
        hongikUniv.Stack s = new hongikUniv.Stack();

        System.out.println(s.hashCode());
    }
}

javatest 패키지에 든 클래스가 hongikUniv 패키지에 든 Stack 클래스를 불러오고 싶을 때 이렇게 가져올 수 있다.

그런데 늘 이렇게 붙여서 설정하면 귀찮고 복잡하고 가동성도 떨어지기 때문에 import를 사용하여 처음 한 번만 패키지 경로를 선언한다. IDE는 설정을 통해서 자동 import를 지원한다.

 

규약

import문은 보통 package문 다음에, calss 선언하기 전에 선언한다. 여러 개를 선언할 수 있다.

 

import 패키지이름.*;
import 패키지이름.클래스이름;

위와 같은 방법으로 선언할 수 있다. *은 모든 클래스를 선언한다.

후자는 실행시 컴파일러가 쉽게 그 클래스를 찾지만 후자는 패키지 경로 내에서 클래스를 찾아야하지만 성능 상의 차이는 없다.

다만 *를 사용할 경우 해당 폴더 내의 클래스만 가져올 수 있지 하위패키지의 클래스는 포함되지 않는다.

 

package javatest;

import hongikUniv.Stack;

public class test {
    public static void main(String[] args) {
        Stack s = new Stack();

        System.out.println(s.hashCode());
    }
}

간결간결

 

java.lang은 묵시적으로 import 문이 자동으로 선언되어 있어 굳이 선언을 하지 않아도 된다.


static import

정적멤버를 호출할 때 클래스 이름을 생략할 수 있다.

 

public class Stack {
    public static void main (String[] args) {
        int e = (int) Math.E;
    }
}

정적클래스하면 늘 나오는 우리 친구 Math 클래스

자연상수 e를 불러오는 메서드를 실행하기 위해서는 Math.E를 통해서 불러와야한다. 뿐만 아니라 Math 클래스를 사용할 일이 많아진다거나 다른 패키지의 정적클래스를 호출할 일이 많아지면 가독성도 떨어지고 코드도 길어진다.

 

import static java.lang.Math.*;

public class Stack {
    public static void main (String[] args) {
        int e = (int) E;
    }
}

이렇게 import 할 때 import static으로 import하면 앞에 클래스명을 붙이지 않고도 import된 인스턴스 변수처럼 사용할 수 있다.

 

import static java.lang.Integer.*;

public class Stack {
    public static void main (String[] args) {
        Integer idx = Integer.valueOf(33);
        Integer idx2 = valueOf(33);
    }
}

메서드에도 동일하게 작용한다.


제어자

클래스, 변수, 메서드 선언부에 사용되어 부가적인 의미를 부여한다.

대표적인 제어자로 접근제어자인 public, private 등이 있으며, 그 외에도 static, final, transient, volatile 등이 있다.

 

staic은 정벅멤버를 선언할 때 사용되고, final은 상수로 선언하여 한 번 값이 변경되면 더이상 값이 변경될 수 없도록 선언한다. 클래스에 사용하면 확장할 수 없다.


접근제어자

접근 가능한 순서대로 접근 가능성이 가장 높은 곳부터 나열을 하면

 

public (접근 제한 없음) - protected(같은 패키지 내에서 또는 다른 패키지의 하위클래스에서 접근 가능) - default(같은 패키지 내에서만 접근가능 | 접근제어자가 없으면 이것으로 설정된다) - private (같은 클래스 내에서만 접근 가능)

 

으로 나뉜다.

 

캡슐화

이러한 접근제어자가 왜 사용되나면, 클래스의 데이터를 보호하기 위함이다. Member 객체에 28세 윤마치를 Member 객체를 넣어놨는데 다음날 갑자기 67세 유재석 Member 객체가 되어버리면 큰 혼란이 생기기 때문에.. private 접근제어자를 사용하여 다른 클래스에서 클래스에 접근하여 클래스 상태를 변경하지 못하게 제한하는 것을 데이터 감추기, 캡슐화라고 한다.

 

또 내부적으로만 사용되는 멤버들을 굳이 외부로 노출시킬 필요가 없으면 private 접근제어자를 통해 노출시키지 않을 수 있다. 이역시 캡슐화에 해당한다.

 

이렇게 내부적으로 인스턴스 변수를 private로 선언해두고, 값을 불러오거나 저장할 수 있는 메서드를 따로 만드는데, 주로 게터세터 (getter / setter)가 사용된다. 게터는 값을 반환하고, 세터는 값을 설정한다. 메서드이기 때문에 유효성검사 과정을 추가할 수 있어 코드도 더욱 효율적으로 작성할 수 있다.

 

확장이 예상되는 클래스라면 protected를 사용해 하위클래스에서 접근가능하도록 설정할 수 있다.


생성자의 접근제어자

생성자 역시 접근제어자를 사용할 수 있다. 아무것도 설정하지 않으면 클래스의 접근제어자와 동일하게 간주된다.

 

private로 접근제어자를 지정하면 생성자를 통해 객체를 생성할 수 없으며, 상속도 불가능하다. 왜냐하면 하위클래스에서 super()를 사용해 상위클래스를 초기화시키는데 private면 불가능하기 때문이다.

생성자가 private인 경우에는 내부적으로 객체를 생성하고 반환하는 메서드를 사용해야한다. 싱글턴 패턴에서 주로 쓰인다. 이 때 객체생성 및 반환을 담당하는 메서드는 public static으로 사용되어야한다.

 

이렇게 접근제어자와 패키지에 대해서 알아봤다.

나름 상속과 다형성이라는 큰 챕터에 낀 작은 챕터의 느낌이 있지만 그래도 유용하다. 헤드퍼스트자바에서는 접근제어자를 public과 private만 소개시켜주기도 했고, 패키지 구조와 정적import도 헤드퍼스트에서 배운 것에서 좀 더 배울 수 있었기 때문에..

'언어공부 > Java | Kotlin' 카테고리의 다른 글

[CS] 자바의 정석 독서 #12 - 추상클래스와 인터페이스  (0) 2025.10.09
[CS] 자바의 정석 독서 #11 - 다형성  (1) 2025.10.09
[CS] 자바의 정석 독서 #9 - 상속  (0) 2025.10.02
[CS] 자바의 정석 독서 #8 - 생성자와 초기화  (0) 2025.10.01
[CS] 자바의 정석 독서 #7 - 메서드 오버로딩  (0) 2025.10.01
'언어공부/Java | Kotlin' 카테고리의 다른 글
  • [CS] 자바의 정석 독서 #12 - 추상클래스와 인터페이스
  • [CS] 자바의 정석 독서 #11 - 다형성
  • [CS] 자바의 정석 독서 #9 - 상속
  • [CS] 자바의 정석 독서 #8 - 생성자와 초기화
Radiata
Radiata
개발을 합니다.
  • Radiata
    DDD
    Radiata
  • 전체
    오늘
    어제
    • 분류 전체보기 (211)
      • 신년사 (3)
        • 2025년 (2)
        • 2026년 (1)
      • CS (59)
        • JVM (12)
        • 백엔드 (20)
        • 언어구현 (1)
        • 객체지향 (1)
        • 논리회로 (5)
        • 컴퓨터구조 (9)
        • 데이터베이스 (1)
        • 컴퓨터 네트워크 (10)
      • 언어공부 (64)
        • Java | Kotlin (48)
        • JavaScript | TypeScript (9)
        • C | C++ (6)
      • 개인 프로젝트 (11)
        • [2025] Happy2SendingMails (3)
        • [2026] 골든리포트! (8)
        • [2026] 순수자바로 개발하기 (0)
        • 기타 이것저것 (0)
      • 팀 프로젝트 (29)
        • [2025][GDG]홍대 맛집 아카이빙 프로젝트 (29)
      • 알고리즘 (13)
        • 백준풀이기록 (11)
      • 놀이터 (0)
      • 에러 수정일지 (2)
      • 고찰 (24)
        • CEOS 23기 회고록 (2)
  • 블로그 메뉴

    • CS
    • 언어공부
    • 개인 프로젝트
    • 팀 프로젝트
    • 알고리즘
    • 고찰
    • 신년사
    • 컬러잇 개발블로그
  • 링크

    • 컬러잇 개발블로그
  • 공지사항

  • 인기 글

  • 태그

    144
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
Radiata
[CS] 자바의 정석 독서 #10 - 패키지와 접근제어자
상단으로

티스토리툴바