목적
자바의 패키지에 대해 학습하세요.
학습할 것
- package 키워드
- import 키워드
- 클래스패스
- CLASSPATH 환경변수
- -classpath 옵션
- 접근지시자
1. package 키워드
패키지
패키지는 클래스랑 인터페이스의 모음이며 관련된 클래스끼리 그룹단위로 모아 효율적인 관리를 할 수 있다.
패키지가 다르면 클래스명이 같아도 구분할 수 있다.
클래스가 물리적으로 하나의 클래스파일(.class).인 것과 같이 패키지는 물리적으로 하나의 디렉토리이다.
하나의 소스파일에 첫 번째 문장으로 단 한 번의 패키지 선언만을 허용한다.
모든 클래스는 반드시 하나의 패키지에 속해야 한다.
패키지는 점(.)을 구분자로 하여 계층구조를 구성할 수 있다.
패키지는 물리적으로 클래스 파일(.class)을 포함하는 하나의 디렉토리이다.
패키지 선언
패키지 선언은 아래 한 줄을 맨 첫번째 줄에 적어주면 된다.
package 패키지명;
2. import키워드
import문
다른 패키지의 클래스를 사용하려 한다면 패키지명이 포함된 클래스 이름을 사용해야 한다. import의 역할은 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공하는 것이다. 이클립스에서 Ctrl + Shift + o 누르면 자동으로 import 해준다.(근데 자동완성에 익숙해져서 잘 안쓸거 같다.)
import문 선언
import 패키지명.클래스명; //한 클래스만 사용할 때
import 패키지명.*; // 패키지 안에 여러클래스를 사용할 때
패키지명.*; 을 사용한다 하면 그안의 모든 클래스들을 로드해 필요없는 클래스도 import 할거라 생각하지만, 실행시 성능에 이상이 없다.
static import문
static import는 static 멤버를 호출할 때 클래스 이름을 생략하게 해준다. 예로
import static java.lang.Math.random;
선언 시,
Math.random(); -> random();
처럼 바꿔준다.
3. 클래스패스
간단히 말해서 클래스를 찾기 위한 경로이다.
우리는 프로그램을 실행하면 메모리를 할당받고 JVM을 동작시킨다.
컴파일러를 실행하게 되면 JVM이 동작하게 된다. JVM은 .java 파일들을 클래스 파일들을 찾는데 그때의 파일 경로의 기준이 된다. 그리고 이를 지정해주는 방법은 classpath 환경변수, -classpath 옵션 두가지가 있다.
4. CLASSPATH 환경변수
JVM 클래스 로더는 classpath 경로를 찾아가 그 안에 정의된 class들을 가져온다.
이 것을 지정해주는 법은 os의 시스템 변수 부분 Path의 값에 %JAVA_HOME%/bin 이라는 값을 추가해주면 등록된다.
5. -classpath 옵션
자바에서 컴파일 할 때 classpath를 정해서 갈 수 있다.
java c -classpath '경로' java파일명
이라는 명령어를 통해서 classpath의 옵션을 지정한다.즉, 다른 클래스에 의존하는 클래스 파일을 컴파일 하기 위해 그 클래스의 경로를 직접 매핑해준다.
6. 접근지시자 (접근제어자)
멤버 또는 클래스에 사용되며, 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할을 한다.
접근제어자가 사용될 수 있는 곳 - 클래스, 멤버변수, 메서드 생성자
제어자 | 같은 클래스 | 같은 패키지 | 자손클래스 | 전 체 |
---|---|---|---|---|
public | O | O | O | O |
protected | O | O | O | |
(default) | O | O | ||
private | O |
public : 접근제한이 전혀 없다.
private : 같은 클래스 내에서만 사용하도록 제한
default : 같은 패키지 내의 클래스에서만 접근 가능
protected : 패키지에 관계없이 상속관계에 있는 자손클래스에서 접근할 수 있도록 하는 것이 제한목적이지만, 같은 패키지내에서도 접근이 가능하다. 결과적으로 protected가 default보다 접근범위가 더 넓다.
접근 제어자를 이용한 캡슐화
접근제어자를 왜 사용하냐 : 클래스 내부에 선언된 데이터를 보호하기 위해서이다. 데이터가 유효한 값을 유지하도록, 비밀번호와 같은 데이터를 외부에서 함부로 변경하지 못하도록 하기 위해서이며 이것을 데이터 감추기라 부르기도 한다.
외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해서도 사용된다.
예를들어
public class Time{
public int hour;
public int minute;
public int second;
}
클래스가 있고 인스턴스 생성 후 멤버변수에 직접 접근하면 값을 변경할 수 있다.
Time t = new Time();
t.hour = 25;
위 코드처럼 hour에 25라는 잘못된 값을 지정한다 해도 막을 방법이 없다.
이럴 때는 private나 protected로 제한하고 값을 읽고 변경할 수 있는 public 메서드를 제공함으로써 간접적으로 멤버변수의 값을 다룰 수 있도록 한다.
public void set Hour(int hour){
if (hour < 0 || hour > 23){
return ;
}
this.hour = hour;
}
만일 상속을 통해 확장될 것이 예상되는 클래스라면, 멤버에 접근 제한을 주되 자손 클래스에서 접근하는 것이 가능하도록 하기 위해 private 대신 protected를 사용한다.
생성자의 접근 제어자
생성자에 접근 제어자를 사용함으로 인스턴스 생성을 제한할 수도 있다.
생성자의 접근 제어자를 private 로 지정하면 외부에서 인스턴스를 생성할 수 없게 된다.
class SingleTon{
private SingleTon() {
}
}
대신 인스턴스를 생성해서 반환해주는 public 메서드를 제공해 외부에서 이 클래스의 인스턴스를 사용할 수 있도록 할 수 있다. 이 메서드는 public 인 동시에 static 이어야 한다.
class Singleton(){
private static Singleton s = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return s;
}
}
또 생성자가 private인 클래스는 다른 클래스의 조상이 될 수 없다. 자손클래스가 인스턴스를 생성할 때 조상클래스의 생성자를 호출해야 하는데 private는 같은 클래스 내에서만 가능하기 때문이다. 따라서 클래스 앞에 final을 더 추가해 상속할 수 없는 클래스인 것을 알려주는 것이 좋다.
제어자의 조합
대 상 | 사용 가능한 제어자 |
---|---|
클래스 | public, (default), final, abstract |
메서드 | 모든 접근 제어자, final, abstract, static |
멤버변수 | 모든 접근 제어자, final, static |
지역변수 | final |
- 메서드에 static과 abstract를 함께 사용할 수 없다.
static 메서드는 구현된 메서드에서만 사용할 수 있기 때문에
- 클래스에 abstract와 final을 동시에 사용할 수 없다.
클래스에서 사용되는 final은 확장을 없애는 의미이고 abstract는 상속을 통해서 완성되기에 모순된다.
- abstract메서드의 접근 제어자가 private일 수 없다.
abstract 메서드는 자손 클래스를 구현해주어야 하는데 접근 제어자가 private 이면 자손에 접근할 수가 없다.
- 메서드에 private가 final을 같이 사용할 수 없다.
접근 제어자가 private인 메서드는 오버라이딩 될 수 없다.
Reference
남궁성. Java의 정석